属性动画技能实践

前言

通过 属性动画原理解析,我们了解属性动画的整个运行机制,对底层的原理有了一定的了解,也学习一些知识点,但是学习过的知识点在没有自己实践都是别人的,只有自己实践后才属于自己的。接下来分享一些属性动画的一些知识点运用项目中的经历。

实践

实践一:屏幕刷新机制

我们知道属性动画基于屏幕刷新回调机制来实时更改属性的值,而在实际的项目应用用,也会很多实时刷新屏幕的需求,接下来我们通过秒表计时器需求来分析刷新机制在实际应用。

秒表计时器的效果图如下所示:

在这里插入图片描述

要实现这个功能就是不停刷新屏幕,更改分针和秒针的旋转角度。要实现这个功能需求,大概有三种方式:

1. Timer+Handler

2. Handler发送延迟消息

3. 利用Choreographer的刷新回调

对于1和2是比较常用的方式,对于3相对用得比较少,只有了解过屏幕刷新机制的才可能会想到用该方法。下面我们就分析3的实现方法:

第一步: 创建实例

private Choreographer choreographer = Choreographer.getInstance();

Choreographer进程启动的时候,内部帮我完成初始化,通过ThreadLocal来进行存储,没有共有构造函数,只能通过Choreographer.getInstance()的方式来获取实例。目前值对外开放了:removeFrameCallback(FrameCallback callback),postFrameCallback(FrameCallback callback),postFrameCallbackDelayed(FrameCallback callback, long delayMillis)。其余的方法都通过 @UnsupportedAppUsage注解限制了外部APP的使用。给我们提供的三个方法里面,最重要的就是FrameCallback,接下来实现回调:

第二步: 实现FrameCallback

在实现FrameCallback之前,先了解FrameCallback的作用

    public interface FrameCallback {
        
        //当新的一帧需要显示的时候会调用该方法
        //这里frameTimeNanos是纳秒,使用过程中除以1000000转换为毫秒
        public void doFrame(long frameTimeNanos);
    }

FrameCallback就一个doFrame()回调方法,具体的说明注释说明。需要更详细的可以参考源码的英文注释。

下面实现我们自己的FrameCallback:

    private Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            if (state == STATE_START) {
                showTime();
                choreographer.postFrameCallback(this);
            }
        }
    };


第三步: 实现计时处理逻辑

    private void showTime() {
        long nowTime = System.currentTimeMillis();
        if (preTime == 0) {
            preTime = nowTime;
        }
        allTime += nowTime - preTime;
        //转换时间格式
        int second = allTime / 1000;
        int mill = allTime % 1000;
        StringBuilder sb = new StringBuilder();
        sb.append(second).append(".");
        sb.append(mill / 100).append((mill % 100) / 10).append("s");
        //其他业务逻辑处理,具体需求具体处理
        Log.d("ChoreographerDemo", sb.toString());
        preTime = nowTime;

    }

在这里只简单的将计时数据输出,和前面的给的效果图有差距,如果实现上面的效果,自己根据UI提供的图进行秒针和分针的旋转即可。

第四步: 测试

完整代码:

public class ChoreographerActivity extends AppCompatActivity {

    private Choreographer choreographer = Choreographer.getInstance();
    //开始
    private static final int STATE_START = 1;
    //暂停
    private static final int STATE_PAUSE = 2;
    private int state;
    //总计时时间
    private int allTime;
    //上一次时间点
    private long preTime;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_choreographer);
    }


    private Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
        @Override
        public void doFrame(long frameTimeNanos) {
            if (state == STATE_START) {
                showTime();
                choreographer.postFrameCallback(this);
            }
        }
    };

    private void showTime() {
        long nowTime = System.currentTimeMillis();
        if (preTime == 0) {
            preTime = nowTime;
        }
        allTime += nowTime - preTime;
        //转换时间格式
        int second = allTime / 1000;
        int mill = allTime % 1000;
        StringBuilder sb = new StringBuilder();
        sb.append(second).append(".");
        sb.append(mill / 100).append((mill % 100) / 10).append("s");
        //其他业务逻辑处理,具体需求具体处理
        Log.d("ChoreographerDemo", sb.toString());
        preTime = nowTime;

    }

    public void pause(View view) {
        state = STATE_PAUSE;
        choreographer.removeFrameCallback(mFrameCallback);
    }

    public void start(View view) {
        state = STATE_START;
        choreographer.postFrameCallback(mFrameCallback);

    }
}

日志数据:

2021-01-19 18:51:41.266 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.00s
2021-01-19 18:51:41.281 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.01s
2021-01-19 18:51:41.300 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.03s
2021-01-19 18:51:41.314 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.04s
2021-01-19 18:51:41.331 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.06s
2021-01-19 18:51:41.348 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.08s
2021-01-19 18:51:41.365 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.09s
2021-01-19 18:51:41.382 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.11s
2021-01-19 18:51:41.398 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.13s
2021-01-19 18:51:41.416 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.15s
2021-01-19 18:51:41.433 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.16s
2021-01-19 18:51:41.450 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.18s
2021-01-19 18:51:41.467 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.20s
2021-01-19 18:51:41.483 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.21s
2021-01-19 18:51:41.500 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.23s
2021-01-19 18:51:41.517 3119-3119/com.water.view.demo D/ChoreographerDemo: 0.25s

小结:

这里目前结合自己的项目经验值分享了屏幕刷新机制的使用,后期发现更多关于动画技能的实践会持续更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值