设计模式(三)Animation中的策略模式

一、基本概念

1、定义:

定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变换。

2、类图:

  • Context对象: 封装可能存在的策略变化,屏蔽其他模块对算法的直接访问
  • Stategy抽象策略:定义通用算法规则
  • ConcreteStategy具体策略:含有具体的算法
3、应用场景:
  • 对调用者隐藏算法具体实现细节
  • 针对同一问题有多种处理方式,需要通过if else等形式选择某一种方式
4、优点:
  • 避免多种处理方式存在的if else语句。方便拓展,多一种处理方式,就多加一个实现类
  • 结构比较清晰,封装性更好
5、缺点:

算法过多会造成多个算法实现类。Context需要了解所有的算法,并做出相应的调用。

二、实例:

例如租房可以通过各种途径,包括中介、房东、朋友等。每一种途径都可以当成一种策略,可以互相切换。

1、抽象策略:
public interface RentingStrategy {
    void renting();
}
复制代码
2、具体策略

中介:

public class AgencyStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过中介租房");
    }
}
复制代码

房东:

public class LandlordStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过房东租房");
    }
}
复制代码

朋友:

public class FriendStrategy implements RentingStrategy {
    @Override
    public void renting() {
        System.out.println("通过朋友租房");
    }
}
复制代码
3、Context
public class Context {
    private RentingStrategy mRentingStrategy;

    public Context(RentingStrategy rentingStrategy) {
        this.mRentingStrategy = rentingStrategy;
    }

    public void rentHouse() {
        this.mRentingStrategy.renting();
    }
}
复制代码
4、调用
public class StrategyTest{
    public static void main(String[] args) {
        RentingStrategy friendStrategy = new FriendStrategy();
        Context context = new Context(friendStrategy);
        context.rentHouse();
    }
}
复制代码

三、动画插值器

动画插值器的作用就是根据时间流逝的百分比来来计算出当前属性值改变的百分比。比如LinearInterpolator用于匀速动画、AccelerateDecelerateInterpolator用于加速减速动画等等。

1、Interpolator
public interface Interpolator extends TimeInterpolator { }

public interface TimeInterpolator {

    /**
     * 返回流逝时间的百分比
     */
    float getInterpolation(float input);
}
复制代码

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

2、LinearInterpolator
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

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

}
复制代码
3、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返回值不同,也就是说算法不同。

4、插值器调用

(1)setInterpolator设置插值器

#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方法来获取动画执行百分比

转载于:https://juejin.im/post/5c7f68696fb9a049c966704d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值