Android 動畫 小結
a.視圖動畫(ViewAnimation)= Tween Animation(補間動畫)+ Frame Animation(逐幀動畫)
b.屬性動畫(property Animator)=ValueAnimator + ObjectAnimator
為什么要使用Property Animator(和view動畫的不同)
1.為了實現view animation 無法實現的效果(view 動畫對派生于view的控件的指定屬性)
2.View Animation僅能對指定的控件做動畫,而Property Animator是通過改變控件某一屬性值來做動畫的。
3.補間動畫雖能對控件做動畫,但并沒有改變控件內部的屬性值。而Property Animator則是恰恰相反,Property Animator是通過改變控件內部的屬性值來達到動畫效果的
一.view動畫的使用:
1.1、XML配置文件中
alpha
漸變透明度動畫效果
scale
漸變尺寸伸縮動畫效果
translate
畫面轉換位置移動動畫效果
rotate
畫面轉移旋轉動畫效果
xml動畫定義
Animation animation =AnimationUtils. loadAnimation(context ,R.anim.xxx);
view.startAnimation(animation);
Animation outAnim = AnimationUtils.loadAnimation(mContext,
R.anim.custom_dialog_disappear);
outAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//todo
}
@Override
public void onAnimationEnd(Animation animation) {
//todo
}
@Override
public void onAnimationRepeat(Animation animation) {
//todo
}
});
view.startAnimation(outAnim);
1.2.代碼使用
final TranslateAnimation animation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 400,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 400);
animation.setFillAfter(true);
animation.setDuration(1000);
tv.startAnimation(animation);
1.3.AnimationSet
構造方法
/**
* Constructor to use when building an AnimationSet from code
*
* @param shareInterpolator Pass true if all of the animations in this set
* should use the interpolator associated with this AnimationSet.
* Pass false if each animation should use its own interpolator.
*/
public AnimationSet(boolean shareInterpolator) {
setFlag(PROPERTY_SHARE_INTERPOLATOR_MASK, shareInterpolator);
init();
}
--
/*
* 將四種動畫效果放入同一個AnimationSet中
*/
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(translateAnimation);
/*
* 同時執行多個動畫效果
*/
view.startAnimation(animationSet);
二.property animator
常用
- ofxxx
- ofObject
- ofPropertyValuesHolder
2.1.value animator
offxxx
ValueAnimator animator = ValueAnimator.ofFloat(startY, endY);
animator.setDuration(300);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedFraction = animation.getAnimatedFraction();
float y = (float) animation.getAnimatedValue();
xxx.setY(y);
xxx.setAlpha(animatedFraction);
}
});
animator.start();
ofObject
/**
* Constructs and returns a ValueAnimator that animates between Object values. A single
* value implies that that value is the one being animated to. However, this is not typically
* useful in a ValueAnimator object because there is no way for the object to determine the
* starting value for the animation (unlike ObjectAnimator, which can derive that value
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
* <p><strong>Note:</strong> The Object values are stored as references to the original
* objects, which means that changes to those objects after this method is called will
* affect the values on the animator. If the objects will be mutated externally after
* this method is called, callers should pass a copy of those objects instead.
*
* <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
* factory method also takes a TypeEvaluator object that the ValueAnimator will use
* to perform that interpolation.
*
* @param evaluator A TypeEvaluator that will be called on each animation frame to
* provide the ncessry interpolation between the Object values to derive the animated
* value.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
*/
public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
ValueAnimator anim = new ValueAnimator();
anim.setObjectValues(values);
anim.setEvaluator(evaluator);
return anim;
}
.
public class CharEvaluator implements TypeEvaluator<Character> {
@Override
public Character evaluate(float fraction, Character startValue, Character endValue) {
int startInt = (int)startValue;
int endInt = (int)endValue;
int curInt = (int)(startInt + fraction *(endInt - startInt));
char result = (char)curInt;
return result;
}
}
--
ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
char text = (char)animation.getAnimatedValue();
tv.setText(String.valueOf(text));
}
});
animator.setDuration(10000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
2.2.object Animator
縮放操作,比如說將TextView在垂直方向上放大3倍再還原,就可以這樣寫:
ObjectAnimator = ObjectAnimator.ofFloat(targetView, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
2.3.animatorSet
AnimatorSet set=new AnimatorSet();
合并播放
源碼
public void playTogether(Animator... items) {
if (items != null) {
Builder builder = play(items[0]);
for (int i = 1; i < items.length; ++i) {
builder.with(items[i]);
}
}
}
set.playTogether(animator1,animator2)
================
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(5000);
animSet.start();
2.4.xml編寫屬性動畫
首先要在res目錄下面新建一個animator文件夾
<animator> 對應代碼中的ValueAnimator
<objectAnimator> 對應代碼中的ObjectAnimator
<set> 對應代碼中的AnimatorSet
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="together" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="sequentially" >
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>
</set>
--
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view);
animator.start();
2.5 PropertyValuesHolder(ObjectAnimator.ofPropertyValuesHolder)
This class holds information about a property and the values that that property
should take on during an animation. PropertyValuesHolder objects can be used to create
animations with ValueAnimator or ObjectAnimator that operate on several different properties in parallel.
PropertyValuesHolder這個類可以先將動畫屬性和值暫時的存儲起來,后一起執行,在有些時候可以使用替換掉AnimatorSet
2.5.1 PropertyValuesHolder.ofKeyframe
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
- propertyName:*動畫所要操作的屬性名
- values:Keyframe的列表,PropertyValuesHolder會根據每個Keyframe的設定,定時將指定的值輸出給動畫。
所以完整的KeyFrame的使用代碼應該是這樣的:
1. Keyframe frame0 = Keyframe.ofFloat(0f, 0);
2. Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
3. Keyframe frame2 = Keyframe.ofFloat(1, 0);
4. PropertyValuesHolder frameHolder = ' PropertyValuesHolder.ofKeyframe ' ("rotation",frame0,frame1,frame2);
5. Animator animator =' ObjectAnimator.ofPropertyValuesHolder ' (mImage,frameHolder);
6. animator.setDuration(1000);
7. animator.start();
2.5.2 PropertyValuesHolder.ofXXX
ObjectAnimator.ofFloat中只比PropertyValuesHolder的ofFloat多了一個target,其它都是完全一樣的
2.5.3 PropertyValuesHolder.ofObject
PropertyValuesHolder charHolder =
PropertyValuesHolder.ofObject("CharText",new CharEvaluator(),new
Character('A'),new Character('Z'));
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView,
charHolder);
animator.setDuration(3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
2.5.4 ObjectAnimator. ofPropertyValuesHolder(view, PropertyValuesHolder_1, PropertyValuesHolder_2 ....)
//keyframe
Keyframe keyframe1 = Keyframe.ofFloat(0.0f,0);
Keyframe keyframe2 = Keyframe.ofFloat(0.25f,-30);
Keyframe keyframe3 = Keyframe.ofFloat(0.5f,0);
Keyframe keyframe4 = Keyframe.ofFloat(0.75f, 30);
Keyframe keyframe5 = Keyframe.ofFloat(1.0f,0);
PropertyValuesHolder rotation = PropertyValuesHolder.ofKeyframe("rotation", keyframe1, keyframe2, keyframe3, keyframe4,keyframe5);
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",1.0f,0.2f,1.0f);
PropertyValuesHolder color = PropertyValuesHolder.ofInt("BackgroundColor", 0XFFFFFF00, 0XFF0000FF);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mButton, alpha, scaleX, scaleY,color,rotation);
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(5000).start();
int riseDelta = ScreenUtil.dp2px(220);
view.setVisibility(View.VISIBLE);
PropertyValuesHolder riseKeyboard = PropertyValuesHolder.ofKeyframe(View.TRANSLATION_Y,
Keyframe.ofFloat(0f, riseDelta),
Keyframe.ofFloat(0.1f, riseDelta * 0.9f),
Keyframe.ofFloat(0.2f, riseDelta * 0.8f),
Keyframe.ofFloat(0.3f, riseDelta * 0.7f),
Keyframe.ofFloat(0.4f, riseDelta * 0.6f),
Keyframe.ofFloat(0.5f, riseDelta * 0.5f),
Keyframe.ofFloat(0.6f, riseDelta * 0.4f),
Keyframe.ofFloat(0.7f, riseDelta * 0.3f),
Keyframe.ofFloat(0.8f, riseDelta * 0.2f),
Keyframe.ofFloat(0.9f, riseDelta * 0.1f),
Keyframe.ofFloat(1f, 0f)
);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, riseKeyboard).
setDuration(300);
animator.setInterpolator(new DecelerateInterpolator());
demo02
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation",
60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder colorHolder =
PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00,
0xffffffff);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView,
rotationHolder, colorHolder);
animator.setDuration(3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
2.6.新api ViewPropertianimator
ViewPropertyAnimator animate = mViewById.animate();
Runnable mStartRun = new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "動畫開始", Toast.LENGTH_SHORT).show();
}
};
Runnable endRun = new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "動畫完成", Toast.LENGTH_SHORT).show();
}
};
animate.alpha(0.5f)
.translationX(100)
.rotationBy(90)
.withStartAction(mStartRun)
.withEndAction(endRun)
.setInterpolator(new OvershootInterpolator())
.start();
}
郭霖的專欄
Android屬性動畫完全解析(上),初識屬性動畫的基本用法
三 . ViewGroup Animation
3.1. LayoutAnimation
- LayoutAnimationController
- GridLayoutAnimationController
3.1.1 LayoutAnimationController
xml 實現
這部分,我們就來看看layoutAnimation標簽的用法,要使用layoutAnimation只需要兩步:
第一:定義一個layoutAnimation的animation文件,如:(anim/layout_animation.xml)
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="1"
android:animationOrder="normal"
android:animation="@anim/slide_in_left"/>
其中的@anim/slide_in_left對應代碼為:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000">
<translate android:fromXDelta="-50%p" android:toXDelta="0"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"/>
</set>
第二步:在viewGroup類型的控件中,添加android:layoutAnimation=”@anim/layout_animation”,如:
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation"
/>
代碼實現 LayoutAnimationController
/**
- A layout animation controller is used to animated a layout's, or a view
- group's, children. Each child uses the same animation but for every one of
- them, the animation starts at a different time. A layout animation controller
- is used by {@link android.view.ViewGroup} to compute the delay by which each
- child's animation start must be offset. The delay is computed by using
- characteristics of each child, like its index in the view group.
- This standard implementation computes the delay by multiplying a fixed
- amount of miliseconds by the index of the child in its parent view group.
- Subclasses are supposed to override
- {@link #getDelayForView(android.view.View)} to implement a different way
- of computing the delay. For instance, a
- {@link android.view.animation.GridLayoutAnimationController} will compute the
- delay based on the column and row indices of the child in its parent view
- group.
- Information used to compute the animation delay of each child are stored
- in an instance of
- {@link android.view.animation.LayoutAnimationController.AnimationParameters},
- itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view.
- @attr ref android.R.styleable#LayoutAnimation_delay
- @attr ref android.R.styleable#LayoutAnimation_animationOrder
- @attr ref android.R.styleable#LayoutAnimation_interpolator
- @attr ref android.R.styleable#LayoutAnimation_animation
*/
public class LayoutAnimationController { .... }
布局與xml的實現方式一樣,唯一不同的是Listview中沒有定義android:layoutAnimation=”@anim/layout_animation”
//代碼設置通過加載XML動畫設置文件來創建一個Animation對象;
Animation animation= AnimationUtils.loadAnimation(this,R.anim.slide_in_left);
//得到一個 'LayoutAnimationController' 對象;
LayoutAnimationController controller = new LayoutAnimationController(animation);
//設置控件顯示的順序;
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
//設置控件顯示間隔時間;
controller.setDelay(0.3f); //為ListView設置LayoutAnimationController屬性;
mListView.setLayoutAnimation(controller);
mListView.startLayoutAnimation();
3.1.2 gridLayoutAnimation
3.1.2.1xml
1)、首先是gride_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:rowDelay="75%"
android:columnDelay="60%"
android:directionPriority="none"
android:animation="@anim/slide_in_left"/>
這里沒有設置android:direction屬性,采用默認值:left_to_right|top_to_bottom;然后是對應的animation動畫slide_in_left.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000">
<translate android:fromXDelta="-50%p" android:toXDelta="0"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0" />
</set>
與LayoutAnimation所使用的動畫一樣,也是從左側50%的位置移動到初始位置,同時透明度從0變到1;
<GridView
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="60dp"
android:gravity="center"
android:horizontalSpacing="10dp"
android:layoutAnimation="@anim/gride_animation"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp"/>
3.1.2.2 代碼使用
GridView grid = (GridView) findViewById(R.id.grid);
mDatas.addAll(getData());
mGrideAdapter = new GridAdapter();
grid.setAdapter(mGrideAdapter);
Animation animation = AnimationUtils.loadAnimation(MyActivity.this,R.anim.slide_in_left);
GridLayoutAnimationController controller = new GridLayoutAnimationController(animation);
controller.setColumnDelay(0.75f);
controller.setRowDelay(0.5f);
controller.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP|GridLayoutAnimationController.DIRECTION_LEFT_TO_RIGHT);
controller.setDirectionPriority(GridLayoutAnimationController.PRIORITY_NONE);
grid.setLayoutAnimation(controller);
grid.startLayoutAnimation();
3.1.2.3 gridLayoutAnimation標簽屬性
directionPriority指gridview動畫優先級,取值有row,column,none.意義分別為行優先,列優先,和無優先級(同時進行)
direction表示gridview的各個item的動畫方向,取值如下,可以通過“|”連接多個屬性值。
取值有四個:
- left_to_right:列,從左向右開始動畫
- right_to_left :列,從右向左開始動畫
- top_to_bottom:行,從上向下開始動畫
- bottom_to_top:行,從下向上開始動畫
3.2 LayoutTransaction
上面雖然在ViewGroup類控件XML中僅添加一行android:animateLayoutChanges=[true]即可實現內部控件添加刪除時都加上動畫效果。但卻只能使用默認動畫效果,而無法自定義動畫。
為了能讓我們自定義動畫,谷歌在API 11時,同時為我們引入了一個類LayoutTransaction。
要使用LayoutTransaction是非常容易的,只需要三步:
a 創建實例
LayoutTransaction transitioner = new LayoutTransition();
b 創建設置動畫
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);
transitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);
c 將LayoutTransaction設置進ViewGroup
linearLayout.setLayoutTransition(mTransitioner);
layoutTransitionGroup = (LinearLayout) findViewById(R.id.layoutTransitionGroup);
findViewById(R.id.add_btn).setOnClickListener(this);
findViewById(R.id.remove_btn).setOnClickListener(this);
mTransitioner = new LayoutTransition();
//入場動畫:view在這個容器中消失時觸發的動畫
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 0f, 360f,0f);
mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn);
//出場動畫:view顯示時的動畫
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);
3.3 listView 動畫
思路 convertView 添加動畫
http://blog.csdn.net/harvic880925/article/details/50988685