做为一个博客《Android其中的动画:Drawable Animation》。android动画主要分为三大部分。上一篇博客已经解说Drawable Animation的使用方法,即逐帧地显示图片,经常运用于动态显示一个进度动画,这是出现频率最高的应用场景。接下来。咱们这篇文章将按部就班。介绍View Animation。html
View Animation也是咱们平时很是多书籍所说的Tweened Animation(有人翻译为补间动画)。View Animation分为4大类:AlphaAnimation,RotateAnimation,ScaleAnimation,TranslateAnimation,分别相应透明度。旋转,大小,位移四种变化。java
View Animation的效果由四个因素决定:1)初始状态。2)结束状态;3)持续时间;4)Interpolator。android
因此要定义一个View Animation,你仅仅要定义以上四个因素,中间的过程怎么变化则有系统本身主动计算出来。windows
当中前3个因素很是easy理解,第四个因素Interpolator比較特别,这个单词不知道怎么翻译比較适合。很是多书籍的翻译都很是奇怪。Interpolator是决定动画进行过程的速度变化。比方:你将一个button从屏幕左側运动到屏幕右側。可以让它一直加速前进。或者先减速而后减速。这就是Interpolator发挥的做用,详细用法如下会说,先从简单的提及。app
像Drawable Animation同样,定义一个View Animation可以用代码的方式,也可以用XML文件的方式。咱们先来写一个最简单的样例,对一个helloworld字符串进行移动。旋转。放大。变暗。分别用代码实现和XML文件实现。ide
先用代码实现。布局
首先新建project:ViewAnimationDemo,并新建一个布局文件:animationjavacode.xml,例如如下:动画
ViewAnimationDemo\res\layout\animationjavacode.xml
ui
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/translation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="50dp" android:text="我要移动" /> <TextView android:id="@+id/rotate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/translation" android:layout_marginBottom="50dp" android:text="我要旋转" /> <TextView android:id="@+id/scale" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/rotate" android:layout_marginBottom="50dp" android:text="我要变大" /> <TextView android:id="@+id/alpha" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/scale" android:layout_marginBottom="200dp" android:text="我要变暗" /> <Button android:id="@+id/fire" android:layout_width="match_parent" android:layout_height="50dp" android:layout_below="@id/alpha" android:text="运动" /> </RelativeLayout>
ViewAnimationDemo/src/com/CSDN/viewanimationdemo/AnimCodeActivity.java
this
public class AnimCodeActivity extends Activity { private TextView translation; private TextView rotate; private TextView scale; private TextView alpha; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.animationjavacode); translation = (TextView) findViewById(R.id.translation); rotate = (TextView) findViewById(R.id.rotate); scale = (TextView) findViewById(R.id.scale); alpha = (TextView) findViewById(R.id.alpha); button = (Button) findViewById(R.id.fire); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 1&2: 肯定起始状态,结束状态 TranslateAnimation tAnim = new TranslateAnimation(0, 400, 0, 0);//横向位移400个单位 RotateAnimation rAnima = new RotateAnimation(0, 70);//顺时针旋转70度 ScaleAnimation sAnima = new ScaleAnimation(0, 5, 0, 5);//横向放大5倍,纵向放大5倍 AlphaAnimation aAnima = new AlphaAnimation(1.0f, 0.0f);//从全不透明变为全透明 // 3: 肯定持续时间 tAnim.setDuration(2000); rAnima.setDuration(2000); sAnima.setDuration(2000); aAnima.setDuration(2000); // 4: 肯定Interpolator tAnim.setInterpolator(new AccelerateDecelerateInterpolator()); // 启动动画 translation.startAnimation(tAnim); rotate.startAnimation(rAnima); scale.startAnimation(sAnima); alpha.startAnimation(aAnima); } }); } }
从代码中不难看到,首先肯定了动画的起始状态和结束状态,而后经过setDuration(2000)设置持续时间,假设这里不设置持续时间,将默以为30mx。基本肉眼看不到。最后咱们设置了一个Interpolator,此处设置效果是动画先减速进行,而后减速。
默认状态时匀速进行。
没错。Interpolator的基本使用方法就是这么easy。以上代码效果图例如如下:
接下来解说怎么用xml定义动画,依照android官网的介绍,定义View Animation的xml文件格式例如如下:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@[package:]anim/interpolator_resource" android:shareInterpolator=["true" | "false"] > <alpha android:fromAlpha="float" android:toAlpha="float" /> <scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float" /> <translate android:fromXDelta="float" android:toXDelta="float" android:fromYDelta="float" android:toYDelta="float" /> <rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float" /> <set> ... </set> </set>
以上需要解说的两个标签属性是android:interpolator和android:shareInterpolator。前者表明你所使用的interpolator。可以是系统自带,也可以是本身定义。
然后者表明,是否将该Interpolator共享给子节点。其余子标签的属性很是easy理解,基本看属性名字就能懂。除了当中两个,android:pivotX和android:pivotY,咱们知道,pivot的意思是轴心的意思,因此这两个属性定义的是这次动画变化的轴心位置,默认是左上角,当咱们把它们二者都赋值为50%,则变化轴心在中心。
接下来写一个详细的样例,例如如下,仍是在刚才的项目中进行。通常咱们把定义动画的xml文件放在res/anim文件夹下,首先咱们新建一个anim文件夹。而后新建一个xml文件,例如如下:
ViewAnimationDemo/res/anim/myanim.xml
<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromXScale="1.0" android:toXScale="1.4" android:fromYScale="1.0" android:toYScale="0.6" android:pivotX="50%" android:pivotY="50%" android:fillAfter="false" android:duration="1000" /> <set android:interpolator="@android:anim/accelerate_interpolator" android:startOffset="1000"> <scale android:fromXScale="1.4" android:toXScale="0.0" android:fromYScale="0.6" android:toYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:duration="400" /> <rotate android:fromDegrees="0" android:toDegrees="60" android:toYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:duration="400" /> </set> </set>
上述样例的效果图例如如下:
上面代码中。有 惟一一个根节点<set>,它有两个子节点<scale>和<set>,而后当中的子节点<set>拥有两个本身的子节点<scale>和<rotate>。
解说一下上面一些没见过的标签属性。
andoird:fillAfter:前面一个样例中,咱们的动画结束后helloworld又回到了原来状态,经过设置fillAfter为true,则动画将保持结束的状态。但是。如前一篇博客《Android动画之中的一个:Drawable Animation》所说,View Animation的动画效果是绘制出来的,并非该组件真正移动了,这个问题咱们兴许会继续探讨。
现在仅仅需要知道将fillAfter设置为true以后。动画将保持结束状态,这大多应用于设计连续发生的动画。
startOffset:该属性定义动画推迟多久開始,经过这个属性的设置,咱们可以设计一些先后按序发生的动画,固然,除了最后一个发生的动画,其它动画得设置fillAfter为true.
interpolator:这里咱们使用了系统自带的interpolator
接下来咱们定义一个布局文件,该布局文件仅仅有一张图片。一个button,经过点击button触发图片进行动画,该布局文件比較简单,这里不列出。怎样在该布局文件相应的activity代码中启动动画呢,代码例如如下:
ViewAnimationDemo/src/com/CSDN/viewanimationdemo/AnimaXmlActivity.java
public class AnimaXmlActivity extends Activity { private Button btn; private ImageView img; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_anima_xml); btn = (Button)findViewById(R.id.xml_btn); img = (ImageView)findViewById(R.id.xmlAnimImg); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Animation anim = AnimationUtils.loadAnimation(AnimaXmlActivity.this, R.anim.myanim); img.startAnimation(anim); } }); } }
到此为止,关于View Animation的基础知识基本已经覆盖了。接下来写一个详细实践的样例,实现经常见到的側滑功能,如网易新闻这样的:
这个側滑的效果实现并不难。很是多人运用了AsyncTask线程,但是结果你会发现有时会发生明显的卡顿,但是假设使用动画效果将会平滑很是多。咱们接下来实现这种功能:
首先新建一个项目:SwipeWithAnim。
并新建一个布局文件activity_main.xml。例如如下
SwipeWithAnim/res/layout/activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <View android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#e23451" /> <LinearLayout android:id="@+id/menu" android:layout_width="400dp" android:layout_height="match_parent" android:layout_gravity="left" android:layout_marginLeft="-380dp" android:orientation="horizontal" > <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#eeeee1" /> <View android:id="@+id/dragArea" android:layout_width="20dp" android:layout_height="match_parent" android:background="#00000000" /> </LinearLayout> </FrameLayout>
SwipeWithAnim/src/com/CSDN/swipewithanim/MainActivity.java
public class MainActivity extends Activity { private View menu; private final static int SHOW_MENU = 1; private final static int HIDE_MENU = -1; private int swipe_tag = SHOW_MENU; private int max_menu_margin = 0; private int min_menu_margin; private float beginX; private float latestX; private float diffX; private float latestMargin; private FrameLayout.LayoutParams lp; /* * (non-Javadoc) * * @see android.app.Activity#onCreate(android.os.Bundle) */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); menu = findViewById(R.id.menu); lp = (FrameLayout.LayoutParams) menu.getLayoutParams(); min_menu_margin = lp.leftMargin; menu.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub int action = MotionEventCompat.getActionMasked(event); switch (action) { case MotionEvent.ACTION_DOWN: beginX = event.getX(); break; case MotionEvent.ACTION_MOVE: latestX = event.getX(); diffX = latestX - beginX; swipe_tag = diffX > 0 ?SHOW_MENU : HIDE_MENU; latestMargin = lp.leftMargin + diffX; if (latestMargin > min_menu_margin && latestMargin < max_menu_margin) { lp.leftMargin = (int) (latestMargin); menu.setLayoutParams(lp); } break; case MotionEvent.ACTION_UP: TranslateAnimation tAnim; if (swipe_tag == SHOW_MENU) { tAnim = new TranslateAnimation(0, max_menu_margin - latestMargin, 0, 0); tAnim.setInterpolator(new DecelerateInterpolator()); tAnim.setDuration(800); menu.startAnimation(tAnim); } else { tAnim = new TranslateAnimation(0, min_menu_margin - latestMargin, 0, 0); tAnim.setDuration(800); menu.startAnimation(tAnim); } //在动画结束的时刻,移动menu的位置。使menu真正移动。 tAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub if (swipe_tag == SHOW_MENU) { lp.leftMargin = max_menu_margin; menu.setLayoutParams(lp); } else { lp.leftMargin = min_menu_margin; menu.setLayoutParams(lp); } menu.clearAnimation(); } }); break; } return true; } }); } }
咱们上面提到,View Animation仅仅是绘制出来的效果,发生动画的组件并非真正移动了,那么此处为了解决问题,咱们监听了AnimationListener。在动画结束时,将menu的位置移动到动画结束的位置,这样就成功移动了menu。效果图例如如下。由于截图软件关系,看起来会卡顿,在真机上測试则全然平滑。
最后附上这篇博客先后的两份源代码: