編輯:關於Android編程
本篇側重講述屬性動畫 ,包含如下內容
- 屬性動畫
- ObjectAnimator 的使用
- ValueAnimator 的使用
- PropertyValuesHolder 的使用
- ViewPropertyAnimator 的使用
- AnimatorSet的使用
- 插值器與估值器淺析
二、屬性動畫
屬性動畫概述
- 屬性動畫是在API11中加入的新特性,在android2.3以下可以使用nineoldandroids兼容庫。
- 屬性動畫是真實改變一個view的相關屬性。而view動畫不能改變一個view的真實屬性。
- 屬性動畫作用對象更加寬泛,不僅限於作用於view,甚至可以沒有作用的對象。
ViewPropertyAnimator的使用
1.示例
@TargetApi(Build.VERSION_CODES.KITKAT)
public void animate(View view) {
final ViewPropertyAnimator animator = view.animate().x(200).y(300).alphaBy(-0.5f).rotationBy(60f).setInterpolator(new BounceInterpolator()).scaleXBy(0.3f).xBy(20).setDuration(2000);
Log.e("TAG", view.getTranslationX() + " : " + view.getX());
animator.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
animator.alpha(1f).xBy(100).scaleY(2f).translationY(100).setDuration(3000).setInterpolator(new CycleInterpolator(5)).start();
Log.e("TAG", "animating...");
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
// 使用此方法 api>19
// animator.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// @Override
// public void onAnimationUpdate(ValueAnimator animation) {
//
// }
// });
animator.start();
}
2.使用解析
1、獲取ViewPropertyAnimator對象
通過view.animate()方法獲取ViewPropertyAnimator對象animator
2、通過animator來改變一個view的屬性
animator.alpha(1f).xBy(100).scaleY(2f).translationY(100).setDuration(3000).setInterpolator(new CycleInterpolator(5));
方法解析:
* x(),y()方法分別改變view的x,y坐標到特定的值,絕對移動
* xBy(offset),yBy(offset),view的x,y坐標的相對改變,相對值(offset),即相對當前移動多少,相對移動(alphaBy,translationXBy()等類似)
* translationX(),translationY()改變的是view的translationX,translationY值,即偏移量
* rotation() 旋轉view到特定的角度
* scaleX(),scaleY() 縮放
* setInterpolator() 設置插值器
* withStartAction(Runnable runnable) 動畫開始動作 API level 16
* withEndAction(Runnable runnable) 動畫結束動作,只有動畫正常結束時進行 API level 16
注:
1、translationX表示的是view的x方向的偏移量(offset,左移為負,右移為正),x表示view的x坐標
2、沒有調用start()方法,動畫依然可以運行,內部隱式啟動,自己也可調用start啟動
3、監聽動畫執行
- animator.setListener 設置動畫狀態監聽
- onAnimationStart 當動畫開始
- onAnimationEnd 當動畫結束
- onAnimationCancel 當動畫取消
- onAnimationRepeat 當動畫重復
- animator.setUpdateListener 設置更新監聽, 使用此方法 api>=19
4、Activity退出時停止動畫,防止內存洩漏
@Override
protected void onDestroy() {
super.onDestroy();
if (animator != null) {
animator.cancel();
animator = null;
}
}
ObjectAnimator 的使用
示例
/**
* ObjectAnimator
*
* @param view
*/
public void objectAnimator(final View view) {
final ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1, 0.5f, 1);
animator.addListener(new Animator.AnimatorListener() { // 設置動畫監聽
@Override
public void onAnimationStart(Animator animation) {
ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f, 1).setDuration(1000).start();
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(1000).start();
}
使用解析
ObjectAnimator是ValueAnimator的繼承類,相比Animation動畫,它並不提供直接的四種動畫子類,而是以of方法來操作view的相關屬性,
常見of方法
- ofArgb(Object target, String propertyName, int... values)
- ofFloat(Object target, String propertyName, float... values)
- ofInt(Object target, String propertyName, int... values)
- ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
- ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
offXXX方法分析
target:指要操作的目標view或對象
propertyName: 指屬性名,諸如alpha,scaleX,scaleY,rotationX,rotationY,translationX,translationY
values: 指操作的屬性的值變化,比如ofFloat(targetView,"alpha",0,1);表示透明度從0到1
PropertyValuesHolder的使用
PropertyValuesHolder可以將設置的屬性變化效果臨時存儲起來,最後一起設置給view
/**
* PropertyValuesHolder的使用
* @param view
*/
public void propertyValuesHolder(View view) {
final PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1, 0.5f, 1);
final PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1, 0.5f, 1);
final PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1, 0.5f, 1);
final ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ivBall, alpha, scaleX, scaleY);
animator.setDuration(1000).start();
}
4.設置動畫監聽
- addListener 添加動畫監聽,可以監聽動畫的開始,取消,結束,重復
- addUpdateListener 添加更新監聽,
- addPauseListener 添加動畫暫停監聽
可以使用AnimatorListenerAdapter選擇性的監聽
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
5.xml中的寫法
6.防止內存洩漏
Activity退出時取消動畫,防止內存洩漏,調用cancel方法即可、
7.使用原則
使用ObjectAnimator 要注意,1、被操作的view的屬性(property)要有set與get方法,2、同時set方法對view的操作能夠反映出來,否則操作失敗
8.對任意對象做動畫
針對以上使用原則若有一條不滿足則會使動畫無效,官方給出三種解決方案
1、如果你有權限的話,給你的對象添加set與get方法
2、用一個類來包裝原始對象,間接為其提供set與get方法
3、采用ViewAnimator,監聽動畫過程,自己實現屬性的改變
ValueAnimator 的使用的使用
ValueAnimator相對ObjectAnimator來說,可以不用操作任何對象,通常是操縱一個值的變化過程,監聽變化的過程,在其中做相應的屬性操作
使用示例
public void valueAnimator(final View view) {
final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(1000);
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float fraction = animation.getAnimatedFraction();
Log.e("TAG", "fraction=" + fraction);
view.setTranslationY((float) (Math.sin(fraction*2*3.14159) * 200));
view.setTranslationX((float) (Math.sin(fraction*2*3.14159) * 200));
}
});
}
使用解析
1、常見ofXXX方法
ofArgb(int... values)
ofFloat(float... values)
ofInt(int... values)
ofPropertyValuesHolder(PropertyValuesHolder... values)
ofObject(TypeEvaluator evaluator, Object... values)
2、設置監聽(同ObjectAnimator)
3、xml中定義ValueAnimator
4、在java代碼中加載動畫
final Animator animator = AnimatorInflater.loadAnimator(AnimatorActivity.this,R.animator.animator_value);
5、還可以設置估值器與插值器
valueAnimator.setEvaluator(new FloatEvaluator());
valueAnimator.setInterpolator(new AccelerateInterpolator());
AnimatorSet的使用
使用示例
1.使用java代碼
public void set(View view) {
AnimatorSet set = new AnimatorSet();
final ObjectAnimator scaleX = ObjectAnimator.ofFloat(ivBall, "scaleX", 1, 0.5f, 1);
final ObjectAnimator scaleY = ObjectAnimator.ofFloat(ivBall, "scaleY", 1, 0.5f, 1);
final ObjectAnimator translationX = ObjectAnimator.ofFloat(ivBall, "translationX", 0, 100, 0);
final ObjectAnimator translationY = ObjectAnimator.ofFloat(ivBall, "translationY", 0, 100, 0);
final ObjectAnimator rotationX = ObjectAnimator.ofFloat(ivBall, "rotationX", 0, 360);
final ObjectAnimator rotationY = ObjectAnimator.ofFloat(ivBall, "rotationY", 0, 360);
final ObjectAnimator alpha = ObjectAnimator.ofFloat(ivBall, "alpha", 1, 0.5f, 1);
// set.playTogether(scaleX, scaleY, translationX, translationY, rotationX, rotationY, alpha); // 一起
// set.playSequentially(scaleX, scaleY, translationX, translationY, rotationX, rotationY, alpha); // 順序
set.play(scaleX).with(scaleY).with(translationX).with(translationY).before(rotationX);
set.play(rotationX).with(rotationY).after(alpha); // 按指定順序
set.setDuration(2000).start();
}
2.在xml中定義動畫
在java代碼中使用定義的動畫
final Animator set = AnimatorInflater.loadAnimator(context,R.animator.animator_set);
set.setTarget(target);
set.start();
3、添加監聽 (同上,三種監聽方式)
使用解析
通過playTogether可以使動畫一起播放,playSequentially使動畫按次序播放,
通過play方法結合with、before、after可以明確指定播放次序,with指兩個動畫一起播放,before、after分別指一個動畫先/後於另一個動畫播放
插值器與估值器淺析
插值器(TimeInterpolator)
1、插值器的概念
插值器定義了動畫變化的速率,通過不同的函數實現,來完成動畫的加速,減速,回彈,彈跳等效果。根據時間流逝的百分比來計算出當前屬性改變的百分比。
2、常見插值器
OvershootInterpolator@android:anim/overshoot_interpolator快速到達終點並超出一小步最後回到終點
AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator先加速再減速
AccelerateInterpolator@android:anim/accelerate_interpolator加速
AnticipateInterpolator@android:anim/anticipate_interpolator先回退一小步然後加速前進
AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator在上一個基礎上超出終點一小步再回到終點
DecelerateInterpolator@android:anim/decelerate_interpolator減速
LinearInterpolator@android:anim/linear_interpolator勻速
BounceInterpolator@android:anim/bounce_interpolator最後階段彈球效果
CycleInterpolator@android:anim/cycle_interpolator周期運動
3、分析CycleInterpolator 源碼
由源碼可以看到插值器輸入的值與返回值關系表達式為:(float)(Math.sin(2 * mCycles * Math.PI * input)),當輸入一直增大時,輸出值在成sin曲線值來回交變,形成所需要的cycle效果
@HasNativeInterpolator
public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public CycleInterpolator(float cycles) {
mCycles = cycles;
}
public CycleInterpolator(Context context, AttributeSet attrs) {
this(context.getResources(), context.getTheme(), attrs);
}
/** @hide */
public CycleInterpolator(Resources resources, Theme theme, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
private float mCycles;
}
4、自定義插值器
自定義Interpolator類實現Interpolator,並實現getInterpolation方法即可
簡單示例:
package com.yu.propertyanimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.animation.Interpolator;
/**
* Created by pecu on 2016/08/27.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
public class MyInterpolator implements Interpolator {
@Override
public float getInterpolation(float input) {
return (float) Math.abs(Math.sin(input * Math.PI)); // 折回效果
}
}
估值器(TypeEvaluator)
通過插值器所獲的屬性改變百分比來估算當前的屬性值
1、 TypeEvaluator接口
先看TypeEvaluator接口,發現只有一個抽象方法evaluate,用於通過fraction來估算出當前值
package android.animation;
public interface TypeEvaluator {
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (x1 - x0),
* where x0 is startValue, x1 is endValue,
* and t is fraction.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* fraction parameter.
public T evaluate(float fraction, T startValue, T endValue);
}
2、查看FloatEvaluator 源碼
可以發現,evaluate方法的返回值是通過這樣一個公式計算所得result = x0 + t * (x1 - x0);
package android.animation;
public class FloatEvaluator implements TypeEvaluator {
/**
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type float or
* Float
* @param endValue The end value; should be of type float or Float
* @return A linear interpolation between the start and end values, given the
* fraction parameter.
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
3、自定義TypeEvaluator
自定義估值器較為簡單,只需要實現TypeEvaluator接口,並重寫evaluate方法即可
一個簡單自定義TypeEvaluator
package com.yu.propertyanimator;
import android.animation.TypeEvaluator;
import android.graphics.Point;
/**
* Created by pecu on 2016/08/27.
*/
public class MyEvaluator implements TypeEvaluator {
Point point;
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
if (point == null) {
point = new Point();
point.x = (int) (startValue.x + fraction * (endValue.x - startValue.x));
point.y = (int) (startValue.y + fraction * (endValue.y - startValue.y));
} else {
point.x = (int) (startValue.x + fraction * (endValue.x - startValue.x));
point.y = (int) (startValue.y + fraction * (endValue.y - startValue.y));
}
return point;
}
}
4、使用自定義的Evaluator
/**
* 仿小球落地後回彈幾次
* @param view
*/
public void evaluate(View view) {
final ValueAnimator valueAnimator = ValueAnimator.ofObject(new MyEvaluator(), new Point(0, 0), new Point(0, screenHeight - 2*ivBall.getHeight()));
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Point point = (Point) animation.getAnimatedValue();
ivBall.setX(point.x);
ivBall.setY(point.y);
}
});
valueAnimator.setDuration(1000);
valueAnimator.start();
}
使用場景在開發中,或許一個業務需求中會出現很多系統控件組合成的布局,並且經常需要復用。比如下圖中 qq或者微博的title欄,在一款app中,可能不同的界面 類似的vie
概述android打包過程,下面這張圖取自Android開發權威指南,非常清晰。整個過程使用的工具有 名稱 功能介紹 在操作系統中的路徑 aapt An
2014的 google i/o發表令多數人為之一亮的 material design toolbar,這是用來取代過去 actionbar 的控件,而現在於 mater
在Android上查看圖片或者浏覽網頁時,我們往往有把圖片或者網頁放大或者縮小的的需求,這樣就能夠獲得更多的細節信息 或者獲得更多的全貌信息,多點觸摸與綻放功能正是滿足這
一直使用Eclipse環境開發Android,也嘗鮮使用過Android