視圖動(dòng)畫:
AlphaAnimation、RotateAnimation、TranslateAnimation、ScaleAnimation 和 動(dòng)畫集:AnimationSet
- AlphaAnimation(透明度動(dòng)畫):
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(1000);
view.startAnimation(alphaAnimation);
- RotateAnimation(旋轉(zhuǎn)動(dòng)畫):
RotateAnimation rotateAnimation = new RotateAnimation(0, 360,
RotateAnimation.RELATIVE_TO_SELF, 0.5F, RotateAnimation.RELATIVE_TO_SELF, 0.5F);
rotateAnimation.setDuration(1000);
view.startAnimation(rotateAnimation);
- TranslateAnimation(位移動(dòng)畫):
TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 0);
translateAnimation.setDuration(1000);
view.startAnimation(translateAnimation);
- ScaleAnimation(縮放動(dòng)畫):
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(1000);
view.startAnimation(scaleAnimation);
- AnimationSet(動(dòng)畫集合):
AnimationSet animationSet = new AnimationSet(true);
animationSet.setDuration(4000);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Log.e(TAG, "onAnimationStart: 動(dòng)畫開始執(zhí)行的時(shí)候調(diào)用");
}
@Override
public void onAnimationEnd(Animation animation) {
Log.e(TAG, "onAnimationEnd: 動(dòng)畫結(jié)束執(zhí)行的時(shí)候調(diào)用");
}
@Override
public void onAnimationRepeat(Animation animation) {
Log.e(TAG, "onAnimationRepeat: 動(dòng)畫重復(fù)執(zhí)行的時(shí)候調(diào)用");
}
});
//啟動(dòng)動(dòng)畫
view.startAnimation(animationSet);
屬性動(dòng)畫
PropertyValuesHolder、Animator、ObjectAnimator 、ValueAnimator
- ObjectAnimator :
ObjectAnimator 是屬性動(dòng)畫框架中最重要的實(shí)行類,創(chuàng)建一個(gè)ObjectAnimator只需要通過它的靜態(tài)工廠類直接返回一個(gè)ObjectAnimator對(duì)象.(通過ofxxx方法);
必須具備get 、set方法,不然ObjectAnimator就無法起效;
- 1.translationX 和 translationY:控制view對(duì)象從布局容器的左下方坐標(biāo)偏移的位置;
- 2.rotation 、rotationX 和 rotationY:控制view對(duì)象圍繞它的支點(diǎn)進(jìn)行2D和3D旋轉(zhuǎn);
- 3.scaleX 和 scaleY: 控制view對(duì)象圍繞它的支點(diǎn)進(jìn)行2D縮放;
- 4.pivotX 和 pivotY:這兩個(gè)屬性控制著View對(duì)象的支點(diǎn)位置, 圍繞這個(gè)支點(diǎn)進(jìn)行旋轉(zhuǎn)和縮放變換處理;
默認(rèn)情況下,該支點(diǎn)的位置就是view的中心點(diǎn);- 5.alpha:它表示view對(duì)象的alpha透明度,默認(rèn)值是1(不透明) ,0代表完全透明(不可見);
如果沒有g(shù)et set方法,那么可以自定義一個(gè)屬性或者包裝類,來間接地給這個(gè)屬性增加get set方法, 或者通過ValueAnimator來實(shí)現(xiàn);
- 自帶屬性:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "translationX", 200);
objectAnimator.setDuration(1000);
objectAnimator.start();
ObjectAnimator animatorColor = ObjectAnimator.ofInt(view,"BackgroundColor",0xffff0000,0xff00ff00);
animatorColor.setEvaluator(new ArgbEvaluator());
animatorColor.setDuration(1000);
animatorColor.start();
- 自定義屬性:
public class WrapperView {
private View view;
public WrapperView(View view) {
this.view =view;
}
public int getWidth(){
return view.getLayoutParams().width;
}
public void setWidth(int width) {
view.getLayoutParams().width = width;
view.requestLayout();
}
}
WrapperView wrapperView = new WrapperView(tvWrapper);
ObjectAnimator objectAnimatorWrapper = ObjectAnimator.ofInt(wrapperView, "width", 100).setDuration(1000);
objectAnimatorWrapper.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.e(TAG, "onAnimationStart: 動(dòng)畫開始執(zhí)行的時(shí)候調(diào)用");
}
@Override
public void onAnimationEnd(Animator animation) {
//這個(gè)應(yīng)該是用得最多的吧
Log.e(TAG, "onAnimationEnd: 動(dòng)畫結(jié)束執(zhí)行的時(shí)候調(diào)用");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.e(TAG, "onAnimationEnd: 動(dòng)畫取消執(zhí)行的時(shí)候調(diào)用");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.e(TAG, "onAnimationEnd: 動(dòng)畫重復(fù)執(zhí)行的時(shí)候調(diào)用");
}
});
objectAnimatorWrapper.start();
- PropertyValuesHolder:
類似AnimationSet
- 動(dòng)畫合并:
PropertyValuesHolder valuesHolderTranslastion = PropertyValuesHolder.ofFloat("translationX", 100f);
PropertyValuesHolder valuesHolderScaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.3f);
PropertyValuesHolder valuesHolderScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.3f);
PropertyValuesHolder valuesHolderColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xff888888, 0xff00ff00);
ObjectAnimator objectAnimatorProper = ObjectAnimator.ofPropertyValuesHolder(tvObjProperty, valuesHolderTranslastion, valuesHolderScaleX, valuesHolderScaleY, valuesHolderColor);
objectAnimatorProper.setDuration(1000);
objectAnimatorProper.start();
- 動(dòng)畫拆分:
// 在 0% 處開始向X移動(dòng)
Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
// 時(shí)間經(jīng)過 50% 的時(shí)候,動(dòng)畫完成度 100%
Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
// 時(shí)間見過 100% 的時(shí)候,動(dòng)畫完成度倒退到 0%位置
Keyframe keyframe3 = Keyframe.ofFloat(1, 0);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", keyframe1, keyframe2, keyframe3);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(tvObjPropertyKey, holder);
animator.start();
- ValueAnimator:
ValueAnimator 是 ObjectAnimator 的父類,ValueAnimator 就是一個(gè)不能指定目標(biāo)對(duì)象版本的 ObjectAnimator
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1000);
valueAnimator.setTarget(view);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO: 2018/10/24
float value = (float) animation.getAnimatedValue();
if (value==500f){
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(100);
view.startAnimation(scaleAnimation);
}
}
});
- Animator:
在
res/animator下創(chuàng)建布局文件,代碼加載xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="2.0"
android:valueType="floatType">
</objectAnimator>
Animator animatorXml = AnimatorInflater.loadAnimator(MainActivity.this,R.animator.animator_xml);
animatorXml.setTarget(view);
animatorXml.start();
AnimationUtils (工具類)
- Android SDK 提供的工具類:
| 返回值 | 公共方法 | 描述 |
|---|---|---|
| static long | currentAnimationTimeMillis() | 以毫秒返回當(dāng)前動(dòng)畫時(shí)間 |
| static Animation | loadAnimation(Context context, int id) | 從資源加載動(dòng)畫對(duì)象 |
| static Interpolator | loadInterpolator(Context context, int id) | 從資源中加載內(nèi)插器對(duì)象 |
| static LayoutAnimationController | loadLayoutAnimation(Context context, int id) | 從資源加載動(dòng)畫對(duì)象(返回值不同) |
| static Animation | makeInAnimation(Context c, boolean fromLeft) | 用布爾參數(shù)決定滑入的方向是左側(cè)還是右側(cè)向上 |
| static Animation | makeInChildBottomAnimation(Context c) | 視圖總是從屏幕的底部向上滑入 |
| static Animation | makeOutAnimation(Context c, boolean toRight) | 用布爾參數(shù)決定滑入的方向是左側(cè)還是右側(cè) |
animation = AnimationUtils.loadAnimation(this, R.anim.animation_utils);
view.startAnimation(animation);
ViewAnimationUtils (5.X的工具類)
createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius)
- centerX : 中心點(diǎn)X坐標(biāo);
- centerY : 中心點(diǎn)Y坐標(biāo);
- startRadius: 動(dòng)畫圓的起始半徑;
- endRadius: 動(dòng)畫圓的結(jié)束半徑.
ViewAnimationUtils.createCircularReveal(ImageView, centerX, centerY, mImageView.getWidth(), 0);
Interpolator(插值器)
Interpolator 其實(shí)就是速度設(shè)置器。你在參數(shù)里填入不同的 Interpolator ,動(dòng)畫就會(huì)以不同的速度模型來執(zhí)行;Google TimeInterpolator
- AccelerateDecelerateInterpolator:
先加速再減速。這是默認(rèn)的 Interpolator;
- LinearInterpolator:
勻速;
- AccelerateInterpolator:
持續(xù)加速;
- DecelerateInterpolator:
以最高速開始,持續(xù)減速直到停止;
- AnticipateInterpolator:
先回退一下段,然后再正常運(yùn)動(dòng);
- OvershootInterpolator:
到終點(diǎn)的時(shí)候超出一下段,然后彈回來;
- AnticipateOvershootInterpolator:
開始前回拉,最后超過一些然后回彈;
- BounceInterpolator:
到達(dá)終點(diǎn)的時(shí)候彈回來兩下,然后回到終點(diǎn);
- CycleInterpolator:
這個(gè)也是一個(gè)正弦 / 余弦曲線,不過它和 AccelerateDecelerateInterpolator 的區(qū)別是,它可以自定義曲線的周期,所以動(dòng)畫可以不到終點(diǎn)就結(jié)束,也可以到達(dá)終點(diǎn)后回彈,回彈的次數(shù)由曲線的周期決定,曲線的周期由 CycleInterpolator() 構(gòu)造方法的參數(shù)決定。
- PathInterpolator:
自定義動(dòng)畫完成度 / 時(shí)間完成度曲線。
用這個(gè) Interpolator 你可以定制出任何你想要的速度模型。定制的方式是使用一個(gè) Path 對(duì)象來繪制出你要的動(dòng)畫完成度 / 時(shí)間完成度曲線
- FastOutLinearInInterpolator(5.0以上):
貝塞爾曲線的持續(xù)加速的運(yùn)動(dòng)路線,AccelerateInterpolator比FastOutLinearInInterpolator斜率要低一點(diǎn);
- FastOutSlowInInterpolator(5.0以上):
貝塞爾曲線,前期加速度要快得多;
- LinearOutSlowInInterpolator(5.0以上):
減速曲線,初始速度更高;
SVG(矢量動(dòng)畫)
-
Android 5.X增加了對(duì)SVG矢量圖的支持(VectorDrawable,AnimatedVectorDrawable):
<path>標(biāo)簽支持的指令: - M: 移動(dòng) moveTo;
- L: 直線;
- H: 水平線;
- V: 垂直線;
- C: 三次貝塞爾曲線;
- S: 三次貝塞爾曲線;
- Q: 二次貝塞爾曲線;
- T: 映射前面路徑后的終點(diǎn);
- Z: 關(guān)閉路徑;
- A: 弧線;
- RX,RY表示橢圓半圓的半軸大小;
- XROTATION表示X軸與水平方向的順時(shí)針方向的夾角;
- FLAG1有兩個(gè)值:1.表示大角度的弧線,0.表示小角度弧線;
- FLAG2有兩個(gè)值,確定從起點(diǎn)至終點(diǎn)的方向:1.表示順時(shí)針,0.表示逆時(shí)針;
- X,Y軸為終點(diǎn)坐標(biāo);
1.大小寫效果一樣,2.坐標(biāo)軸和canvas一樣左上角(0,0),3.指令和數(shù)據(jù)間的空格可以省略,4.同個(gè)指令出現(xiàn)多個(gè)時(shí)候可以只用一個(gè)。
defaultConfig {
//配置信息
vectorDrawables.useSupportLibrary = true
}
<!--res/drawable下新建-->
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="100dp"
android:width="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<group>
<path
android:name="path1"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="5"
android:strokeLineCap="round"
android:pathData="M 20,80 L 50,80 80,80"/>
</group>
<group>
<path
android:name="path2"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="5"
android:strokeLineCap="round"
android:pathData="M 20,20 L 50,20 80,20"/>
</group>
</vector>
<!--res/animator下新建-->
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="pathData"
android:valueFrom="M 20,80 L 50,80 80,80"
android:valueTo="M 20,80 L 50,50 80,80"
android:valueType="pathType"
android:interpolator="@android:anim/bounce_interpolator">
</objectAnimator>
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:propertyName="pathData"
android:valueFrom="M 20,20 L 50,20 80,20"
android:valueTo="M 20,20 L 50,50 80,20"
android:valueType="pathType"
android:interpolator="@android:anim/bounce_interpolator">
</objectAnimator>
<!--res/drawble-v21下新建-->
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/svg_line">
<target
android:name="path1"
android:animation="@animator/animator_svg_path1"/>
<target
android:name="path2"
android:animation="@animator/animator_svg_path2"/>
</animated-vector>
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Drawable drawable = imageViewSVG.getDrawable();
if (drawable instanceof Animatable){
((Animatable) drawable).start();
}
}