刚开始的思路
- 属性动画?(可以实现,但是估计只为这个业务做这么大量的动画会吐血)
- 帧动画?(设计师会吐血)
- 视频播放?(没错,就是它了)
为了证实自己的思路,继续抱着崇拜的心态解压了apk,发现果然啊,有个18s的mp4文件,拿到这个后再想实现这个效果就太尼玛容易了。
ps:我觉得单独这样拿文件并开源是种不太好的行为,所以向目前在流利说的前同事稍微请示了下,心里踏实些~
下面开始手摸手分析:
- 18s的动画分成了三部分
- 引导页也是三页,而且每一页都在循环对应的6s
- 播放mp4可以用VideoView
- 播放至指定位置可以用VideoView暴露的seekTo(int msec)
所有问题迎刃而解,so easy啊。
那么可以开始手摸手撸码了:
一、视频文件放入src/raw文件夹内
插句嘴,这里可以温习下常见面试题,src/raw与assets的区别?
放入后读取相关文件:
1 2 3 4 5 6 7 8 | private String getVideoPath() { return "android.resource://" + this.getPackageName() + "/" + R.raw.intro_video; } |
二、VideoView准备播放
1 2 | mVideoView = (PreviewVideoView) findViewById(R.id.vv_preview); mVideoView.setVideoURI(Uri.parse(getVideoPath())); |
三、轮询每一页的6s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private Subscription mLoop; private void startLoop() { if (null != mLoop) { mLoop.unsubscribe(); } mLoop = Observable.interval(0, 6 * 1000, TimeUnit.MILLISECONDS) .subscribe(new Action1() { @Override public void call(Long aLong) { mVideoView.seekTo(mCurrentPage * 6 * 1000); if (!mVideoView.isPlaying()) { mVideoView.start(); } } }); } |
关于何时startLoop我就不赘述了,一个是启动后,一个是ViewPager滑动后。
看似好像完成了所有操作,其实不然,最后一步尤为重要!
四、确保VideoView全屏且尽量不拉伸
冲着这个标题就知道要重写VideoView的onMeasure()方法了。
1 2 3 4 5 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int w = MeasureSpec.getSize(widthMeasureSpec); setMeasuredDimension(w, (int) (w / 0.56f)); } |
宽度保持全屏,高度用宽度/0.56,很多人会问,0.56哪来的?请看图:
mp4文件是1080*1920的,宽/长约等于0.56,很简单吧。
资源均来自第三方,谨慎下载,前往第三方网站下载