設計模式(三)Animation中的策略模式

1、基本概念

一、定義:

定義了一系列的算法,並將每個算法封裝起來,並且使它們還能夠相互替換。策略模式讓算法獨立於使用它的客戶而獨立變換。算法

二、類圖:

  • Context對象: 封裝可能存在的策略變化,屏蔽其餘模塊對算法的直接訪問
  • Stategy抽象策略:定義通用算法規則
  • ConcreteStategy具體策略:含有具體的算法

三、應用場景:

  • 對調用者隱藏算法具體實現細節
  • 針對同一問題有多種處理方式,須要經過if else等形式選擇某一種方式

四、優勢:

  • 避免多種處理方式存在的if else語句。方便拓展,多一種處理方式,就多加一個實現類
  • 結構比較清晰,封裝性更好

五、缺點:

算法過多會形成多個算法實現類。Context須要瞭解全部的算法,並作出相應的調用。canvas

2、實例:

例如租房能夠經過各類途徑,包括中介、房東、朋友等。每一種途徑均可以當成一種策略,能夠互相切換。緩存

一、抽象策略:

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("經過朋友租房");
    }
}
複製代碼

三、Context

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();
    }
}
複製代碼

3、動畫插值器

動畫插值器的做用就是根據時間流逝的百分比來來計算出當前屬性值改變的百分比。好比LinearInterpolator用於勻速動畫、AccelerateDecelerateInterpolator用於加速減速動畫等等。動畫

一、Interpolator

public interface Interpolator extends TimeInterpolator { }

public interface TimeInterpolator {

    /**
     * 返回流逝時間的百分比
     */
    float getInterpolation(float input);
}
複製代碼

定義接口和策略可提供的方法ui

二、LinearInterpolator

@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

}
複製代碼

三、AccelerateDecelerateInterpolator

@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方法來獲取動畫執行百分比

相關文章
相關標籤/搜索