【HenCoder Android 開發(fā)進(jìn)階】自定義 View 1-7:屬性動畫(進(jìn)階篇)
針對特殊類型的屬性來做屬性動畫;
針對復(fù)雜的屬性關(guān)系來做屬性動畫督函。
TypeEvaluator
TypeEvaluator 最經(jīng)典的用法是使用 ArgbEvaluator 來做顏色漸變的動畫。
ObjectAnimator animator = ObjectAnimator.ofInt(view, "color", 0xffff0000, 0xff00ff00);
animator.setEvaluator(new ArgbEvaluator());
animator.start();
自定義 Evaluator
// 自定義 HslEvaluator
private class HsvEvaluator implements TypeEvaluator<Integer> {
float[] startHsv = new float[3];
float[] endHsv = new float[3];
float[] outHsv = new float[3];
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
// 把 ARGB 轉(zhuǎn)換成 HSV
Color.colorToHSV(startValue, startHsv);
Color.colorToHSV(endValue, endHsv);
// 計算當(dāng)前動畫完成度(fraction)所對應(yīng)的顏色值
if (endHsv[0] - startHsv[0] > 180) {
endHsv[0] -= 360;
} else if (endHsv[0] - startHsv[0] < -180) {
endHsv[0] += 360;
}
outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;
if (outHsv[0] > 360) {
outHsv[0] -= 360;
} else if (outHsv[0] < 0) {
outHsv[0] += 360;
}
outHsv[1] = startHsv[1] + (endHsv[1] - startHsv[1]) * fraction;
outHsv[2] = startHsv[2] + (endHsv[2] - startHsv[2]) * fraction;
// 計算當(dāng)前動畫完成度(fraction)所對應(yīng)的透明度
int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);
// 把 HSV 轉(zhuǎn)換回 ARGB 返回
return Color.HSVToColor(alpha, outHsv);
}
}
ObjectAnimator animator = ObjectAnimator.ofInt(view, "color", 0xff00ff00);
// 使用自定義的 HslEvaluator
animator.setEvaluator(new HsvEvaluator());
animator.start();
借助于 TypeEvaluator浸遗,屬性動畫就可以通過 ofObject() 來對不限定類型的屬性做動畫了埠通。方式很簡單:
為目標(biāo)屬性寫一個自定義的 TypeEvaluator
使用 ofObject() 來創(chuàng)建 Animator骑祟,并把自定義的 TypeEvaluator 作為參數(shù)填入
PropertyValuesHolder 同一個動畫中改變多個屬性
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 1);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder1, holder2, holder3)
animator.start();
AnimatorSet 多個動畫配合執(zhí)行
ObjectAnimator animator1 = ObjectAnimator.ofFloat(...);
animator1.setInterpolator(new LinearInterpolator());
ObjectAnimator animator2 = ObjectAnimator.ofInt(...);
animator2.setInterpolator(new DecelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
// 兩個動畫依次執(zhí)行
animatorSet.playSequentially(animator1, animator2);
// 兩個動畫同時執(zhí)行
animatorSet.playTogether(animator1, animator2);
// 使用 AnimatorSet.play(animatorA).with/before/after(animatorB)
// 的方式來精確配置各個 Animator 之間的關(guān)系
animatorSet.play(animator1).with(animator2);
animatorSet.play(animator1).before(animator2);
animatorSet.play(animator1).after(animator2);
animatorSet.start();
PropertyValuesHolders.ofKeyframe() 把同一個屬性拆分
// 在 0% 處開始
Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
// 時間經(jīng)過 50% 的時候声怔,動畫完成度 100%
Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
// 時間見過 100% 的時候态贤,動畫完成度倒退到 80%,即反彈 20%
Keyframe keyframe3 = Keyframe.ofFloat(1, 80);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("progress", keyframe1, keyframe2, keyframe3);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, holder);
animator.start();
「關(guān)于復(fù)雜的屬性關(guān)系來做動畫」醋火,就這么三種:
1.使用 PropertyValuesHolder 來對多個屬性同時做動畫抵卫;
2.使用 AnimatorSet 來同時管理調(diào)配多個動畫;
3.PropertyValuesHolder 的進(jìn)階使用:使用 PropertyValuesHolder.ofKeyframe() 來把一個屬性拆分成多段胎撇,執(zhí)行更加精細(xì)的屬性動畫。
ValueAnimator 最基本的輪子
遵循一個原則就行:盡量用簡單的殖氏。能用 View.animate() 實現(xiàn)就不用 ObjectAnimator晚树,能用 ObjectAnimator 就不用 ValueAnimator。