定義了一系列的算法,並將每個算法封裝起來,並且使它們還能夠相互替換。策略模式讓算法獨立於使用它的客戶而獨立變換。算法
算法過多會形成多個算法實現類。Context須要瞭解全部的算法,並作出相應的調用。canvas
例如租房能夠經過各類途徑,包括中介、房東、朋友等。每一種途徑均可以當成一種策略,能夠互相切換。緩存
public interface RentingStrategy {
void renting();
}
複製代碼
中介:bash
public class AgencyStrategy implements RentingStrategy {
@Override
public void renting() {
System.out.println("經過中介租房");
}
}
複製代碼
房東:app
public class LandlordStrategy implements RentingStrategy {
@Override
public void renting() {
System.out.println("經過房東租房");
}
}
複製代碼
朋友:ide
public class FriendStrategy implements RentingStrategy {
@Override
public void renting() {
System.out.println("經過朋友租房");
}
}
複製代碼
public class Context {
private RentingStrategy mRentingStrategy;
public Context(RentingStrategy rentingStrategy) {
this.mRentingStrategy = rentingStrategy;
}
public void rentHouse() {
this.mRentingStrategy.renting();
}
}
複製代碼
public class StrategyTest{
public static void main(String[] args) {
RentingStrategy friendStrategy = new FriendStrategy();
Context context = new Context(friendStrategy);
context.rentHouse();
}
}
複製代碼
動畫插值器的做用就是根據時間流逝的百分比來來計算出當前屬性值改變的百分比。好比LinearInterpolator用於勻速動畫、AccelerateDecelerateInterpolator用於加速減速動畫等等。動畫
public interface Interpolator extends TimeInterpolator { }
public interface TimeInterpolator {
/**
* 返回流逝時間的百分比
*/
float getInterpolation(float input);
}
複製代碼
定義接口和策略可提供的方法ui
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
}
複製代碼
@HasNativeInterpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
}
複製代碼
不一樣的插值器區別在於getInterpolation返回值不一樣,也就是說算法不一樣。this
(1)setInterpolator設置插值器spa
#Animation
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
複製代碼
經過setInterpolator設置某個插值器(某種策略)
(2)View的startAnimation
#View
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
//設置動畫
setAnimation(animation);
//刷新父類緩存
invalidateParentCaches();
//刷新View跟子View
invalidate(true);
}
複製代碼
invalidate會對View進行重繪,調用View的draw方法
(3)draw
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
......
final Animation a = getAnimation();
if (a != null) {
more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
......
}
}
複製代碼
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
......
//設置動畫開始監聽
onAnimationStart();
}
......
invalidationTransform = parent.mInvalidationTransformation;
//獲取到動畫的相關值
a.getTransformation(drawingTime, invalidationTransform, 1f);
} else {
invalidationTransform = t;
}
if (more) {
......
// 獲取重繪的區域
final RectF region = parent.mInvalidateRegion;
a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
invalidationTransform);
parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
// 從新計算區域
final int left = mLeft + (int) region.left;
final int top = mTop + (int) region.top;
// 進行更新
parent.invalidate(left, top, left + (int) (region.width() + .5f),
top + (int) (region.height() + .5f));
}
}
return more;
}
複製代碼
(4)Animation.getTransformation
裏面實現了動畫的具體值的改變
public boolean getTransformation(long currentTime, Transformation outTransformation) {
......
//經過插值器獲取動畫執行百分比
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
applyTransformation(interpolatedTime, outTransformation);
}
......
return mMore;
}
複製代碼
內部經過調用Interpolator的getInterpolation方法來獲取動畫執行百分比