Android View動畫
Animation 框架定義了透明度椎木、旋轉(zhuǎn)灭红、縮放和位移幾種常見的動畫为肮,而且控制的是整個View叉钥。
- 以下是一些常用動畫的設(shè)置
- 注意:View動畫改變的只是VIew的顯示效果罢缸,而不改變View的響應(yīng)區(qū)域
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void btnAlpha(View view) {
AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(3000);
view.startAnimation(aa);
}
public void btnRotate(View view) {
//0 :旋轉(zhuǎn)起始角度
//360 : 旋轉(zhuǎn)終止角度
//0,0 :繞那個點(diǎn)旋轉(zhuǎn)
RotateAnimation ra = new RotateAnimation(0, 270, 0, 0);
ra.setDuration(3000);
view.startAnimation(ra);
}
public void btnRotateSelf(View view) {
RotateAnimation ra = new RotateAnimation(0, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(3000);
view.startAnimation(ra);
}
public void btnTranslate(View view) {
//0 : x起始位置
//200 :x結(jié)束位置
//0 : y起始位置
//300 :y結(jié)束位置
TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
ta.setDuration(3000);
view.startAnimation(ta);
}
public void btnScale(View view) {
//1 : x起始大小
//1 : x結(jié)束大小
//0 : y起始大小
//2 : y結(jié)束大小
ScaleAnimation sa = new ScaleAnimation(1, 1, 0, 2);
sa.setDuration(3000);
view.startAnimation(sa);
}
public void btnScaleSelf(View view) {
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(3000);
view.startAnimation(sa);
}
public void btnSet(View view) {
//動畫組
AnimationSet as = new AnimationSet(true);
as.setDuration(3000);
//透明度動畫
AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(3000);
as.addAnimation(aa);
//平移動畫
TranslateAnimation ta = new TranslateAnimation(0, 100, 0, 200);
ta.setDuration(3000);
as.addAnimation(ta);
//啟動動畫
view.startAnimation(as);
}
}
Android屬性動畫
由于Animation框架改變的只是顯示效果投队,并不能相應(yīng)事件枫疆, 因此,在Android3.0之后引入了屬性動畫框架(Animator)敷鸦;Animator框架中使用最多的是AnimatorSet和ObjectAnimator的配合养铸。
- ObjectAnimator
ObjectAnimator是屬性動畫框架中的最重要的實(shí)行類,創(chuàng)建一個ObjectAnimator只需通過他的靜態(tài)工廠類直接返回一個ObjectAnimator對象轧膘,參數(shù)包括一個對象和對象的屬性钞螟,但屬性必須有g(shù)et和set函數(shù)。
ObjectAnimator animator = ObjectAnimator.ofFloat( view, "translationX", 300); animator.setDuration(300); animator.start();
ObjectAnimator : 常用動畫屬性說明
- translationX 和 translationY :這兩個屬性通常用來控制view的平移谎碍。
- rotaion鳞滨、rotationX、rotationY :這三個屬性控制view對象圍繞支點(diǎn)進(jìn)行2D和3D旋轉(zhuǎn)蟆淀。
- scaleX 和 scaleY :這兩個屬性控制view對象圍繞它的支點(diǎn)進(jìn)行2D縮放拯啦。
- pivotX 和 privotY :這兩個屬性控制view對象的支點(diǎn)位置,圍繞這個支點(diǎn)進(jìn)行旋轉(zhuǎn)和縮放變換處理熔任。默認(rèn)情況下褒链,該支點(diǎn)位置就是view對象的中心點(diǎn)。
- x 和 y :這兩個屬性描述了view對象在它的容器中的最終位置疑苔,它是最初的做坐標(biāo)和tranlationX 和 translationY值的累計(jì)和甫匹。
- alpha : 表示view對象的alpha透明度,默認(rèn)值是1(不透明)惦费,0代表完全透明(不可見)兵迅。
注:如果一個屬性沒有g(shù)et、set方法薪贫,也通過包裝類的方法給屬性增加get恍箭、set方法來實(shí)現(xiàn)動畫,代碼如下:
> private static class WrapperView {
private View mTarget;
public WrapperView(View target) {
mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
通過以上代碼瞧省,就給屬性提供了set扯夭、get方法鳍贾,使用時(shí)只需要操作包裝類即可
> WrapperView wrapper = new WrapperView(view);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(3000).start();
- PropertyValuesHolder
類似視圖動畫的AnimationSet,屬性動畫如果對同個對象要定義多個屬性交洗,就要用刀PropertyValuesHolder來實(shí)現(xiàn)贾漏。
> //同時(shí)操作多個屬性動畫
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(3000).start();
- ValueAnimator
ValueAnimator在屬性動畫中占有非常重要的地位,他本身不提供任何動畫效果藕筋,他更像一個數(shù)值產(chǎn)生器纵散,用來產(chǎn)生具有一定規(guī)律的數(shù)字,從而讓調(diào)用者來控制動畫的實(shí)現(xiàn)過程隐圾。
> //ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0, 400);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
//TODO use the value
if (value < 200) {
ObjectAnimator.ofFloat(view, "translationX", 200).setDuration(1000).start();
} else {
ObjectAnimator.ofFloat(view, "translationY", 200).setDuration(1000).start();
}
}
});
- 動畫事件的監(jiān)聽
一個完整的動畫具有Start伍掀、Repeat、End暇藏、Cancel四個過程蜜笤,通過Android提供的API可以很方便的監(jiān)聽這四個事件
> ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//動畫開始時(shí)
}
@Override
public void onAnimationEnd(Animator animation) {
//動畫結(jié)束時(shí)
}
@Override
public void onAnimationCancel(Animator animation) {
//動畫取消時(shí)
}
@Override
public void onAnimationRepeat(Animator animation) {
//動畫重復(fù)時(shí)
}
});
- AnimatorSet
對于一個對象同時(shí)作用多個屬性動畫,可以用PropertyValuesHolder實(shí)現(xiàn)盐碱,同樣也可以用AnimatorSet實(shí)現(xiàn)把兔,而且AnimatorSet同時(shí)也能實(shí)現(xiàn)更為精確的順序控制。
>//使用AnimatorSet實(shí)現(xiàn)作用多個動畫
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();
AnimatorSet正是通過playTogether()瓮顽、playSequentially()县好、animSet.play().with()、before暖混、after()等方法來對多個動畫的播放順序做精確的控制的缕贡。
- View的animate方法
在Android3.0之后,google給view增加了animate方法來直接設(shè)置屬性動畫拣播。代碼如下
>//通過view的animate方法直接設(shè)置屬性動畫
view.animate().alpha(0).y(300).setDuration(3000).withStartAction(new Runnable() {
@Override
public void run() {
//動畫開始時(shí)
}
}).withEndAction(new Runnable() {
@Override
public void run() {
//動畫結(jié)束時(shí)
}
}).start();
}
Android布局動畫
布局動畫晾咪,是指作用在ViewGroup上的動畫,當(dāng)ViewGroup增加view時(shí)添加一個動畫的過渡效果贮配。
最簡單的布局動畫是在ViewGroup的XML中谍倦,使用以下代碼來設(shè)置android:animateLayoutChanges="true"
另外還可通過LayoutAnimationController類來自定義一個子View的過渡效果。
LinearLayout ll = (LinearLayout)findViewById(R.id.ll); //設(shè)置過渡動畫 ScaleAnimation sa = new ScaleAnimation(0, 1, 0,1); sa.setDuration(2000); //設(shè)置布局動畫的顯示屬性 LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F); lac.setOrder(LayoutAnimationController.ORDER_NORMAL); //為ViewGroup設(shè)置布局動畫 ll.setLayoutAnimation(lac);
LayoutAnimationController的第一個參數(shù)是需要作用的動畫泪勒,第二個參數(shù)是每個子view的顯示時(shí)間昼蛀,當(dāng)delay時(shí)間不為0時(shí)可以設(shè)置子view顯示的順序
- LayoutAnimationController.ORDER_NORMAL--正序
- LayoutAnimationController.ORDER_RANDOM -- 隨機(jī)
- LayoutAnimationController.ORDER_REVERSE -- 反序
- Interpolators(插值器)
通過插值器,可以定義動畫變換的速率酣藻,有點(diǎn)類似于物理中的加速度曹洽。主要作用是用來控制目標(biāo)變量的變化值然后進(jìn)行對應(yīng)的操作鳍置。
自定義動畫
創(chuàng)建自定義動畫辽剧,通常情況下只需要覆蓋父類的initialize方法來實(shí)現(xiàn)一些初始化工作,并且實(shí)現(xiàn)applyTransformation邏輯就可以了税产。
> public
class
CustomAnim extends Animation
{
private int mCenterWidth;
private int mCenterHeight;
private Camera mCamera = new Camera();
private float mRotateY = 0.0f;
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
//設(shè)置默認(rèn)時(shí)長
setDuration(2000);
//設(shè)置動畫結(jié)束后保留狀態(tài)
setFillAfter(true);
//設(shè)置默認(rèn)插值器
setInterpolator(new BounceInterpolator());
mCenterHeight = height/2;
mCenterWidth = width/2;
}
//暴漏一個接口給外界設(shè)置旋轉(zhuǎn)角度
public void setRotateY(float rotateY) {
mRotateY = rotateY;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
//獲得當(dāng)前的矩陣對象
final Matrix matrix = t.getMatrix();
mCamera.save();
//使用Camera設(shè)置旋轉(zhuǎn)的角度
mCamera.rotateY(mRotateY * interpolatedTime);
//將旋轉(zhuǎn)變化作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();
//通過pre方法設(shè)置矩陣作用前的偏移量來改變旋轉(zhuǎn)中心
matrix.preTranslate(mCenterWidth, mCenterHeight);
matrix.postTranslate(-mCenterWidth, -mCenterHeight);
}
}
在上面這個例子中用到了Camera怕轿,這里的Camera不是指手機(jī)中的相機(jī)偷崩,而是android.graphics.Camera中的Camera類,它封裝了openGL的3D動畫撞羽,從而可以非常方便的創(chuàng)建3D動畫效果阐斜。使用的時(shí)候就是通過設(shè)置三個坐標(biāo)軸(X、y诀紊、z)的旋轉(zhuǎn)角度谒出,從而實(shí)現(xiàn)3d動畫的效果
>mCamera.save();
//使用Camera設(shè)置旋轉(zhuǎn)的角度
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateZ(mRotateY * interpolatedTime);
//將旋轉(zhuǎn)變化作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();
SVG矢量動畫
SVG : 可伸縮適量圖形,于Bitmap(位圖)相比邻奠,最明顯的優(yōu)點(diǎn)是放大不會失真笤喳。
-
<path>
標(biāo)簽
使用
<path>
標(biāo)簽創(chuàng)建SVG,就像用指令的方式來控制一只畫筆碌宴,例如移動畫筆到某一坐標(biāo)位置杀狡,畫一條直線,畫一條曲線等贰镣。常用<path>
指令有以下幾種:
- M = moveto(M X, Y) : 將畫筆移動到指定的坐標(biāo)位置呜象,但未發(fā)生繪制。
- L = lineto(L X, Y) : 畫直線到指定的坐標(biāo)位置
- H = horizontal lineto(H X) : 畫水平線到指定的x坐標(biāo)位置碑隆。
- V = vertical lineto(V Y) : 畫垂直線到指定的Y坐標(biāo)位置恭陡。
- C = curveto(C X1, Y1, x2, Y2, ENDX, ENDY) : 三次貝塞爾曲線。
- S = smooth curveto(S X2, Y2, ENDX, ENDY) : 三次貝塞爾曲線上煤。
- Q = quadraic Belzier curve(Q X, Y, ENDX, ENDY) : 二次貝塞爾曲線子姜。
- T = smooth quadratic Belzier curveto(T ENDX, ENDY) : 映射前面路徑后的終點(diǎn)。
- A = cliptical Arc(A RX, RY, XROTATION, FLAG1, FLAG2, x, y) : 弧線楼入。
- Z = closepath() : 關(guān)閉路徑哥捕。
注:使用這些指令需注意以下幾點(diǎn)
- 坐標(biāo)軸以(0, 0) 為中心,X軸水平向右嘉熊, Y軸水平向下遥赚。
- 所有指令大小寫均可,大寫表示絕對定位阐肤,參照全局坐標(biāo)系凫佛;小寫相對定位,參照父容器坐標(biāo)系孕惜。
- 指令和數(shù)據(jù)間的空格可以省略愧薛。
- 同一指令出現(xiàn)多次可以只用一個。
- Android中使用SVG
Goggle在Android5.x中提供了VectorDrawable和AnimatedVectorDrawable兩個API來幫助支持SVG衫画,首先使用VectorDrawable來創(chuàng)建基于XML的SVG圖形毫炉,再結(jié)合AnimatedVectorDrawable來實(shí)現(xiàn)動畫效果。