转自:http://blog.csdn.net/CrazyMo_/article/details/51085365
引言
前一篇Android进阶——属性动画Property Animation详解(一)总结了属性动画的绝大部分核心知识点,这篇主要是补充下欠缺的知识点——Layout布局动画和View的动画相关知识、自定义TypeEvaluator属性动画的应用。
一、布局Layout改变时应用动画
首先我们必须先把对应的ViewGrop的Android:animateLayoutchanges属性设置为true。
1、使用Java代码应用Layout change 动画步骤
ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone;当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类(该类是Android 提供的用于动画显示ViewGroup中的Layout的帮助类,我们可以使用该类设置动画并绑定目标Layout)应用,当ViewGroup的视图层次发生变化时产生过渡的动画效果。
方法 | 用法释义 | LayoutTransition()构造方法void addTransitionListener(LayoutTransition.TransitionListener listener)添加监听void setAnimator(int transitionType, Animator animator)设置指定的Animatorvoid setInterpolator(int transitionType, TimeInterpolator interpolator)设置Interpolatorvoid setStagger(int transitionType, long duration)设置延迟时间~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LayoutTransition Type | 用法释义 | APPEARING当一个元素在其父元素中变为Visible时对这个元素应用动画CHANGE_APPEARING当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画CHANGE_DISAPPEARING当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画CHANGING不是因为View被添加或消失而造成对其他View位置造成影响,对其他View应用动画DISAPPEARING当一个元素在其父元素中变为GONE时对其应用动画1.1、首先通过构造方法得到LayoutTransition对象
LayoutTransition transition = new LayoutTransition();
1.2、setAnimator设置Animator和监听(如果业务需求的话)
需要注意的是传递的Animator应用的对象的属性必须具有完整的getter和setter。
transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim)
transition.addTransitionListener(new LayoutTransition.TransitionListener() { @Override public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) { } @Override public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) { } });
1.3、ViewGroup对象调用setLayoutTransition即可。
mLayout.setLayoutTransition(transition)
2、使用xml形式应用Layout change 动画步骤
Layout change动画的xml文件的根节点是layout-animation。
- android:delay表示动画播放的延时,既可以是百分比,也可以是float小数。
- android:animationOrder表示动画的播放顺序,有三个取值normal(顺序)、reverse(反序)、random(随机),当然也可以自定义。
- android:animation指向了子控件所要播放的动画。
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="30%" android:animationOrder="reverse" android:animation="@anim/slide_right"/>
就可以将layout-animation应用到ViewGroup中,xml布局添加下面一行就
android:layoutAnimation="@animator/animator_main_layout"
也可以代码配置,如果在xml中文件已经写好LayoutAnimation,可以使用AnimationUtils直接加载:
AnimationUtils.loadLayoutAnimation(context, id)
LayoutAnimationController控制动画的显示顺序
//通过加载XML动画设置文件来创建一个Animation对象; Animation animation=AnimationUtils.loadAnimation(this, R.anim.slide_right) LayoutAnimationController controller = new LayoutAnimationController(animation) controller.setOrder(LayoutAnimationController.ORDER_REVERSE) controller.setDelay(0.3) listView.setLayoutAnimation(controller) listView.startLayoutAnimation()
3、Keyframes
keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象。
例:设置btn2对象的width属性值使其:
Keyframe kf0 = Keyframe.ofInt(0, 400);Keyframe kf1 = Keyframe.ofInt(0.25f, 200);Keyframe kf2 = Keyframe.ofInt(0.5f, 400);Keyframe kf4 = Keyframe.ofInt(0.75f, 100);Keyframe kf3 = Keyframe.ofInt(1f, 500);PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);rotationAnim.setDuration(2000);
定义了一些Keyframe后,通过PropertyValuesHolder类的方法ofKeyframe一个PropertyValuesHolder对象,然后通过ObjectAnimator.ofPropertyValuesHolder获得一个Animator对象。
ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500)oa.setDuration(2000)oa.start()
4、ViewPropertyAnimator
当需要对一个View的多个属性进行动画可以用ViewPropertyAnimator类,该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图。
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 260f)PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 260f)ObjectAnimator.ofPropertyValuesHolder(mImg, pvhX, pvyY).start()mImg.animate().x(50f).y(100f)
5、Layout改变动画的实例
例1,首先看一个简单一点的添加按钮的时候产生宽度逐渐变大的动画
![这里写图片描述](http://img.blog.csdn.net/20160408114851966)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rootLinearLayout" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical" android:animateLayoutChanges="true" > <TextView android:id="@+id/id_addbtn_txt" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="点击添加按钮并伴随动画效果" /></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="3000" android:propertyName="alpha" android:valueFrom="0" android:valueTo="1"> ></objectAnimator>
package com.crazymo.anim;public class LayoutChangeActivity extends Activity { private LinearLayout mRootLinearLayout; private Context mContext; private TextView mTextView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layoutchange); init(); } private void init() { mContext = this; mRootLinearLayout = (LinearLayout) findViewById(R.id.rootLinearLayout); mTextView = (TextView) findViewById(R.id.id_addbtn_txt); mTextView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Button addedButton = new Button(mContext); addedButton.setText("LayoutChange"); ObjectAnimator objectAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(mContext, R.animator.animator_scale); objectAnimator.setTarget(addedButton); LayoutTransition layoutTransition = new LayoutTransition(); layoutTransition.setAnimator(LayoutTransition.APPEARING, objectAnimator); mRootLinearLayout.setLayoutTransition(layoutTransition); mRootLinearLayout.addView(addedButton); } }); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
例2,上例中,当Layout改变时应用的只是一种动画效果,如果直接把动画文件改为set节点的动画集,运行是报错的(Java.lang.ClassCastException: android.animation.AnimatorSet cannot be cast to android.animation.ObjectAnimator),接下来我们应用多种效果,包含添加和删除View时的动画。
![这里写图片描述](http://img.blog.csdn.net/20160408160501253)
<LinearLayout 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:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="Add Button" android:id="@+id/layout_animator_addbutton" /> <Button android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="Reset Button" android:id="@+id/layout_animator_resetbutton" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <GridLayout android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="4" android:animateLayoutChanges="true" android:id="@+id/layout_animator_gridview" /> </ScrollView></LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
package com.crazymo.anim;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.Keyframe;import android.animation.LayoutTransition;import android.animation.ObjectAnimator;import android.animation.PropertyValuesHolder;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.GridLayout;import android.widget.LinearLayout;public class ComplexLayoutAnimActivity extends Activity implements View.OnClickListener { private Button mButtonAdd; private Button mButtonReset; private GridLayout mGridLayout; private int buttonNumbers = 1; private LayoutTransition mLayoutTransition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_complexanim); initViews(); } private void getViews() { mButtonAdd = (Button) findViewById(R.id.layout_animator_addbutton); mButtonAdd.setOnClickListener(this); mButtonReset = (Button) findViewById(R.id.layout_animator_resetbutton); mButtonReset.setOnClickListener(this); mGridLayout = (GridLayout) findViewById(R.id.layout_animator_gridview); } public void initViews() { getViews(); mLayoutTransition = new LayoutTransition(); mGridLayout.setLayoutTransition(mLayoutTransition); mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 30); mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30); mLayoutTransition.setDuration(300); customLayoutTransition(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.layout_animator_addbutton: Log.d("TAG", "add btn"); addButton(); break; case R.id.layout_animator_resetbutton: Log.d("TAG", "reset btn"); resetButton(); break; default: break; } } /** * 增加Button */ public void addButton() { Button mButton = new Button(this); LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(270, 150); mButton.setLayoutParams(mLayoutParams); mButton.setText("Button" + String.valueOf(buttonNumbers++)); mButton.setTextColor(Color.rgb(0, 0, 0)); if (buttonNumbers % 2 == 1) { mButton.setBackgroundColor(Color.GREEN); } else { mButton.setBackgroundColor(Color.RED); } mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mGridLayout.removeView(v); } }); mGridLayout.addView(mButton, Math.min(1, mGridLayout.getChildCount())); } /** * 删除所有的Button,重置GridLayout */ public void resetButton() { mGridLayout.removeAllViews(); buttonNumbers = 1; } public void customLayoutTransition() { /** * Add Button * LayoutTransition.APPEARING * 增加一个Button时,设置该Button的动画效果 */ ObjectAnimator mAnimatorAppearing = ObjectAnimator.ofFloat(null, "rotationY", 90.0f, 0.0f) .setDuration(mLayoutTransition.getDuration(LayoutTransition.APPEARING)); mLayoutTransition.setAnimator(LayoutTransition.APPEARING, mAnimatorAppearing); mAnimatorAppearing.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); View view = (View) ((ObjectAnimator) animation).getTarget(); view.setRotationY(0.0f); } }); /** * Add Button * LayoutTransition.CHANGE_APPEARING * 当增加一个Button时,设置其他Button的动画效果 */ PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); PropertyValuesHolder mHolderScaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f, 1.0f); PropertyValuesHolder mHolderScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f, 1.0f); ObjectAnimator mObjectAnimatorChangeAppearing = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom, mHolderScaleX, mHolderScaleY).setDuration(mLayoutTransition .getDuration(LayoutTransition.CHANGE_APPEARING)); mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mObjectAnimatorChangeAppearing); mObjectAnimatorChangeAppearing.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); View view = (View) ((ObjectAnimator) animation).getTarget(); view.setScaleX(1f); view.setScaleY(1f); } }); /** * Delete Button * LayoutTransition.DISAPPEARING * 当删除一个Button时,设置该Button的动画效果 */ ObjectAnimator mObjectAnimatorDisAppearing = ObjectAnimator.ofFloat(null, "rotationX", 0.0f, 90.0f) .setDuration(mLayoutTransition.getDuration(LayoutTransition.DISAPPEARING)); mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mObjectAnimatorDisAppearing); mObjectAnimatorDisAppearing.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); View view = (View) ((ObjectAnimator) animation).getTarget(); view.setRotationX(0.0f); } }); /** * Delete Button * LayoutTransition.CHANGE_DISAPPEARING * 当删除一个Button时,设置其它Button的动画效果 */ Keyframe mKeyframeStart = Keyframe.ofFloat(0.0f, 0.0f); Keyframe mKeyframeMiddle = Keyframe.ofFloat(0.5f, 180.0f); Keyframe mKeyframeEndBefore = Keyframe.ofFloat(0.999f, 360.0f); Keyframe mKeyframeEnd = Keyframe.ofFloat(1.0f, 0.0f); PropertyValuesHolder mPropertyValuesHolder = PropertyValuesHolder.ofKeyframe("rotation", mKeyframeStart, mKeyframeMiddle, mKeyframeEndBefore, mKeyframeEnd); ObjectAnimator mObjectAnimatorChangeDisAppearing = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom, mPropertyValuesHolder) .setDuration(mLayoutTransition.getDuration(LayoutTransition.CHANGE_DISAPPEARING)); mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mObjectAnimatorChangeDisAppearing); mObjectAnimatorChangeDisAppearing.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); View view = (View) ((ObjectAnimator) animation).getTarget(); view.setRotation(0.0f); } }); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
二、View 的animate系方法
使用其实很简单通过View的animate()方法构造一个ViewPropertyAnimator对象,然后设置动画效果。
![这里写图片描述](http://img.blog.csdn.net/20160408171716688)
package com.crazymo.anim;public class ViewAnimActivity extends Activity{ private final String TAG="ViewAnimActivity"; private ImageView mBall; private float mScreenHeight; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.layout); DisplayMetrics outMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(outMetrics); mScreenHeight = outMetrics.heightPixels; mBall = (ImageView) findViewById(R.id.id_ball); } public void viewAnim(View view){ mBall.animate() .alpha(0) .scaleX(0.1f) .scaleY(0.1f) .setInterpolator(new AccelerateDecelerateInterpolator()) .y(mScreenHeight / 2).setDuration(2000) .withStartAction(new Runnable(){ @Override public void run(){ Log.e(TAG, "START"); } }) .withEndAction(new Runnable(){ @Override public void run(){ Log.e(TAG, "END"); runOnUiThread(new Runnable() { @Override public void run(){ mBall.setY(0); mBall.setAlpha(1.0f); } }); } }).start(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
三、属性动画的应用例子
1、采用ValueAnimator,监听动画过程,自己实现属性的改变
private void performAnimate(final View target, final int start, final int end) { ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); valueAnimator.addUpdateListener(new AnimatorUpdateListener() { private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animator) { int currentValue = (Integer)animator.getAnimatedValue(); Log.d(TAG, current value: + currentValue); float fraction = currentValue / 100f; target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end); target.requestLayout(); } }); valueAnimator.setDuration(5000).start();}@Overridepublic void onClick(View v) { if (v == mButton) { performAnimate(mButton, mButton.getWidth(), 500); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
ValueAnimator我要再说一下,拿上例来说,它会在5000ms内将一个数从1变到100,然后动画的每一帧会回调onAnimationUpdate方法,在这个方法里,我们可以获取当前的值(1-100),根据当前值所占的比例(当前值/100),我们可以计算出Button现在的宽度应该是多少,比如时间过了一半,当前值是50,比例为0.5,假设Button的起始宽度是100px,最终宽度是500px,那么Button增加的宽度也应该占总增加宽度的一半,总增加宽度是500-100=400,所以这个时候Button应该增加宽度400*0.5=200,那么当前Button的宽度应该为初始宽度+ 增加宽度(100+200=300)。上述计算过程很简单,其实它就是整型估值器IntEvaluator的内部实现。
2、使用ObjectAnimator对View的任意属性使用属性动画
例:对Button的宽度实现从当前宽度增加到屏幕的一半宽度。
![这里写图片描述](http://img.blog.csdn.net/20160407172326552)
/**如果只是使用这个方法你会发现,为什么我们对Button的width属性做了动画却没有效果?上一篇讲过使用属性动画必须满足几个前提,Button内部虽然提供了getWidth和setWidth方法,但是这个setWidth方法并不是改变视图的大小,它继承自TextView新添加的方法,View是没有这个setWidth方法的。阅读了下源码,追踪发现总之,TextView和Button的setWidth和getWidth对应的对象不同,getWidth是可以获取到View 的宽度,然而setWidth设置的确不是View的宽度,而是设置TextView及其子类的宽度。*/private void buttonAnimate() { WindowManager wm = (WindowManager)getApplicationContext() .getSystemService(Context.WINDOW_SERVICE); int mScreenWidth= wm.getDefaultDisplay().getWidth()/2; ObjectAnimator.ofInt(mButton, width, mScreenWidth).setDuration(4000).start();}
网上查到,对任何属性做动画有三种方案:
package com.crazymo.anim;/** * Created by cmo on 16-4-7. */public class BtnPropertyAnimActivity extends Activity { private Button mBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_button); mBtn= (Button) findViewById(R.id.id_anim_btn); mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ViewWrapper viewWrapper=new ViewWrapper(mBtn); WindowManager wm = (WindowManager)getApplicationContext() .getSystemService(Context.WINDOW_SERVICE); int mScreenWidth= wm.getDefaultDisplay().getWidth(); int width=mBtn.getMeasuredWidth(); ObjectAnimator.ofInt(viewWrapper, "width",width, mScreenWidth).setDuration(4000).start(); } }); } private static class ViewWrapper { private View mTarget; public ViewWrapper(View target) { mTarget = target; } public int getWidth() { return mTarget.getLayoutParams().width; } public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 采用ValueAnimator,监听动画过程,自己实现属性的改变
/**它会在4000ms内将一个数从1变到100,然后动画的每一帧会回调onAnimationUpdate方法,在这个方法里,我们可以获取当前的值(1-100),根据当前值所占的比例(当前值/100),我们可以计算出Button现在的宽度应该是多少,比如时间过了一半,当前值是50,比例为0.5,假设Button的起始宽度是100px,最终屏幕宽度是500px,那么Button增加的宽度也应该占总增加宽度的一半,总增加宽度是500-100=400,所以这个时候Button应该增加宽度400*0.5=200,那么当前Button的宽度应该为初始宽度+ 增加宽度(100+200=300)。*/private void buttonAnimate(final View target, final int start, final int end) { ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); valueAnimator.addUpdateListener(new AnimatorUpdateListener() { private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animator) { int currentValue = (Integer)animator.getAnimatedValue(); float fraction = currentValue / 100f; target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end); target.requestLayout(); } }); valueAnimator.setDuration(4000).start();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
3、自定义动画展示顺序
我们都知道LayoutAnimation默认只有三种顺序,即顺序、逆序和随机,有时候并不能满足需求。比如说将动画顺序改为左上到右下角展开,例如Material Design中这个样子。(虽然一个个按顺序播放页可以实现)但是。去翻翻源码看它是怎么实现的,有没有提供方法自定义顺序?结果翻到了一个LayoutAnimationController#getTransformedIndex(AnimationParameters params)方法,返回值就是播放动画的顺序。并且这个方法是protected的,明显就是可由子类来扩展。
![这里写图片描述](http://www.jcodecraeer.com/uploads/20150915/1442313422121422.gif)
/** * custom LayoutAnimationController for playing child animation in any order. */public class CustomLayoutAnimationController extends LayoutAnimationController { public static final int ORDER_CUSTOM = 7; private Callback onIndexListener; public void setOnIndexListener(OnIndexListener onIndexListener) { this.onIndexListener = onIndexListener; } public CustomLayoutAnimationController(Animation anim) { super(anim); } public CustomLayoutAnimationController(Animation anim, float delay) { super(anim, delay); } public CustomLayoutAnimationController(Context context, AttributeSet attrs) { super(context, attrs); } /** * override method for custom play child view animation order */ protected int getTransformedIndex(AnimationParameters params) { if(getOrder() == ORDER_CUSTOM && onIndexListener != null) { return onIndexListener.onIndex(this, params.count, params.index); } else { return super.getTransformedIndex(params); } } /** * callback for get play animation order */ public static interface Callback{ public int onIndex(CustomLayoutAnimationController controller, int count, int index); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
//通过加载XML动画设置文件来创建一个Animation对象; Animation animation=AnimationUtils.loadAnimation(this, R.anim.slide_right) CustomLayoutAnimationController controller = new LayoutAnimationController(animation) controller.setOrder(CustomLayoutAnimationController.ORDER_COSTOM) controller.setDelay(0.3) listView.setLayoutAnimation(controller) listView.startLayoutAnimation()
通过复写getTransformedIndex方法,添加自定义顺序ORDER_CUSTOM,让callback自定义控件播放动画的顺序,即可以达到任何想要的效果。
0 0