原创安卓手机QQ7.0登录界面动态背景视频实现方案
qq7.0登录界面动态背景实现 qq7.0登录界面动态视频背景实现 android动态视频背景 android动态背景
分析qq7.0:
视频在打开登录界面就开始播放 了,而且期间无黑屏
而且是循环播放的
画质问题这里就不说了,这个看视频源了。
可以让不规则的宽高各种宽高不定的视频比例 以及视频大小都能 适应任意安卓手机的宽高 包括平板,且不留任何缝隙
播放器控件选取:解决的是手机适配的问题,另外是播放器控件,这里选择系统播放器比较好. 因为有些播放器不支持读取asset文件夹的Uri比如七牛的
视频加载速度比较慢第一帧用图片代替且需要耦合视频的第一帧
图片的第一帧截取我用的是一个比较专业的adobe premiere的开发工具 这个你们也可以让ps等后期的去做,这种事情对我来说的话还是小kiss,
技术点:
如何读取资源文件视频
如何测量
如何根据视频大小计算应该缩放的比例大小 解决任意尺寸视频手机不留黑边
如何让图片的封面缩放大小和视频的缩放大小吻合
如何调用onStart短暂黑屏问题
架构搭建
资源的读取
String VIDEO_PATH = "android.resource://" + BuildConfig.APPLICATION_ID + "/" + R.raw.login;
videoView.setVideoURI(Uri.parse(Constants.VIDEO_PATH));
创建一个自定义视频类 自定义图片类 图片在视频的上面因为视频不是马上播放 加载有一定时间这里也会存在一个黑屏
关于读取视频的问题,之前尝试过读取assests里面的视频失败了,在stackoverflow照的方案也不行,最后还是把视频放到和res/raw文件夹里面了,
具体实现之视频控件
1. 拿到视频的宽高度才能进行测量重新布局
在继承的VideoView里添加setOnPreparedListener方法获取视频宽高度设置给成员变量就可以拿到了
super.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(final MediaPlayer mp) {SystemVideoView.this.videoWidth = mp.getVideoWidth();SystemVideoView.this.videoHeight = mp.getVideoHeight();}
}
2. 继承VideoView重写onMeasure测量方法
需要一个完美的算法来解决宽高都铺满屏幕问题
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);MeasureUtil.Size measure = MeasureUtil.measure(displayAspectRatio, widthMeasureSpec, heightMeasureSpec, videoWidth, videoHeight);setMeasuredDimension(measure.width, measure.height);}
这里的算法比较麻烦,不懂的同学搬用模版代码
测量工具类MeasureUtil.measure方法抽出来
的大致代码是
public static MeasureUtil.Size measure(int displayAspectRatio, int widthMeasureSpec, int heightMeasureSpec, int videoWidth, int videoHeight) {if (widthMode == View.MeasureSpec.EXACTLY && heightMode == View.MeasureSpec.EXACTLY) { if (percentVideo > percentView) {width = widthSize;height = (int) ((float) widthSize / percentVideo);} else {height = heightSize;width = (int) ((float) heightSize * percentVideo);}}else if (widthMode == View.MeasureSpec.EXACTLY) {width = widthSize;height = widthSize * videoHeight / videoWidth;if (heightMode == View.MeasureSpec.AT_MOST && height > heightSize) {height = heightSize;}} else if (heightMode == View.MeasureSpec.EXACTLY) {height = heightSize;width = heightSize * videoWidth / videoHeight;if (widthMode == View.MeasureSpec.AT_MOST && width > widthSize) {width = widthSize;}} else {width = videoWidth;height = videoHeight;if (heightMode == View.MeasureSpec.AT_MOST && videoHeight > heightSize) {height = heightSize;width = heightSize * videoWidth / videoHeight;}if (widthMode == View.MeasureSpec.AT_MOST && width > widthSize) {width = widthSize;height = widthSize * videoHeight / videoWidth;}}}public static class Size {public final int width;public final int height;public Size(int width, int height) {this.width = width;this.height = height;}}
3. 黑屏问题解决探讨
只要调用start就会有一定概率的黑屏毫秒
先不管测量铺满问题,我们发现会存在一个坑,就是视频黑屏问题,进入这个界面肯定要让它不黑屏的.
1.尝试过在onPrepared里面再在让VideoView显示隐藏结果没卵用
1.直接隐藏控件在方案1的基础上延长几秒,start过程中依然隐藏(不同手机需要的延长时间不同,)但是如果0秒到1秒的过程中如果没有画面动还好,如果动了,延长超过1秒后在显示此控件那么视频就需要留长 不然首帧和此时videoview显示的时间不一致,后面发现这种死办法又没法解决循环播放问题
最后的解决方法通过百度找到 是根据info的视频第一帧来判断:
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {if (onCorveHideListener != null) {onCorveHideListener.requestHide();}}if (onInfoListener != null) {onInfoListener.onInfo(mp, what, extra);}return false;}});
图片的解决方案和视频一样,你这都需要代码得话打赏一个吧,哈哈,
隐藏的方法在外面了。叫 setOnCorveHideListener ,实际上进入界面就应该马上显示画面的隐藏视频的话是一个白屏,所以这里需要
最后界面activity或者fragment代码
String VIDEO_PATH = "android.resource://" + BuildConfig.APPLICATION_ID + "/" + R.raw.login;loginActivityBinding.videoView.setDisplayAspectRatio(MeasureUtil.ASPECT_RATIO_PAVED_PARENT);loginActivityBinding.videoView.setOnCorveHideListener(new SystemVideoView.OnCorveHideListener() {@Overridepublic void requestHide() {loginActivityBinding.corver.setVisibility(View.GONE);}});loginActivityBinding.videoView.setVideoURI(Uri.parse(Constants.VIDEO_PATH));loginActivityBinding.videoView.start();loginActivityBinding.videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {loginActivityBinding.videoView.seekTo(0);loginActivityBinding.videoView.start();}});@Overridepublic void onPause() {super.onPause();loginActivityBinding.videoView.pause();}@Overridepublic void onResume() {super.onResume();loginActivityBinding.videoView.start();}
完整SystemVideoView代码
public class SystemVideoView extends VideoView {private int videoWidth;//widthprivate int videoHeight;private int displayAspectRatio;public SystemVideoView(Context context) {super(context);}public SystemVideoView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public SystemVideoView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}protected void init(Context context) {this.videoHeight = context.getResources().getDisplayMetrics().heightPixels;this.videoWidth = context.getResources().getDisplayMetrics().widthPixels;super.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(final MediaPlayer mp) {SystemVideoView.this.videoWidth = mp.getVideoWidth();SystemVideoView.this.videoHeight = mp.getVideoHeight();mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {if (onCorveHideListener != null) {onCorveHideListener.requestHide();}}if (onInfoListener != null) {onInfoListener.onInfo(mp, what, extra);}return false;}});}});}MediaPlayer.OnPreparedListener onPreparedListener = null;public interface OnCorveHideListener {void requestHide();}@Overridepublic void setOnInfoListener(MediaPlayer.OnInfoListener onInfoListener) {this.onInfoListener = onInfoListener;}MediaPlayer.OnInfoListener onInfoListener;public void setOnCorveHideListener(OnCorveHideListener onCorveHideListener) {this.onCorveHideListener = onCorveHideListener;}OnCorveHideListener onCorveHideListener;@Overridepublic void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {this.onPreparedListener = l;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);MeasureUtil.Size measure = MeasureUtil.measure(displayAspectRatio, widthMeasureSpec, heightMeasureSpec, videoWidth, videoHeight);setMeasuredDimension(measure.width, measure.height);public void setDisplayAspectRatio(int var1) {displayAspectRatio = var1;this.requestLayout();}@Overridepublic boolean isPlaying() {return false;}public int getDisplayAspectRatio() {return displayAspectRatio;}public void setCorver(int resource) {BitmapFactory.Options opts = new BitmapFactory.Options();opts.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), resource, opts);}
我的博客
我的简书
原创安卓手机QQ7.0登录界面动态背景视频实现方案相关推荐
- 安卓手机 8.0系统以上 webview添加视频录制功能报错
Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on 解决方案:WebChromeClient中重写 ...
- 安卓学习笔记3——登录界面UI
安卓学习笔记3--登录界面UI 一.登录界面UI 1.根据需求写UI 2.主活动 3.主活动调用的读写文件的工具类 4.效果展示 二.总结与改进 不足: 1.密码分割采用字符串:当密码和用户名包含该字 ...
- 视频消重软件吾爱伪原创 安卓手机怎么看视频md5
视频消重软件吾爱伪原创 安卓手机怎么看视频md5 一百家公司爆炸并不容易.有必要慢慢发展主题和对内容的敏感性.. 可以说社会视角文章适合普通大众,覆盖大量用 ...
- jquery自己主动旋转的登录界面的背景代码登录页背景图
在其他网站上看到比较爽Web登录界面.背景图片可以自己主动旋转. 介绍给大家.有兴趣的可以改改下来作为自己的系统登录界面. 如图: 下载源代码 版权声明:本文博客原创文章,博客,未经同意,不得转载. ...
- 怎么修改计算机密码界面的背景,操作方法:在Win10中输入密码时如何修改登录界面的背景图片(两种方法)...
Win10系统的登录背景默认为"英雄"墙纸.我相信许多朋友对此感到厌倦. Win10没有提供自由更改的选项,但是我们可以通过某些方法或工具来更改登录背景. 方法1:手动修改 Win ...
- android 4.0.4 usb调试,安卓手机4.0怎么打开usb调试?图文详解附视频
安卓手机更新换代的太快,系统每次升级多少会有点不同 总会有那么点不适应,就连如何调试USB都不知道怎么设置了? 下面就来就讲讲目前主流品牌手机4.0手机USB调试. 大部分Android设备打开&qu ...
- 测试android运行电流电压,[原创]安卓手机查看充放电电压、电流及功率
版权声明:本文系作者原创,读者可随意网上转载,但请保留此版权声明.如果有什么问题需要讨论.发现错误想指正或者有其它出版意向,请通过新浪博客http://blog.sina.com.cn/felonwa ...
- QQ2012Beta1_1.82.4428.0登录界面和皮肤透明化修改------具体的文件修改方法
QQ2012请往下拉 废话不多说,直接进入正题,先上几张效果图!!! 以上呢就是我所用的了,自己可以根据自己的喜好,剪辑好的图片换上去,分辨率好像没什么要求,但不要太小了, 用到的工具,通用文件打包解 ...
- 从安卓手机恢复删除重要文件、照片或视频的应用程序列表
有时我们会意外地从Android设备中删除需要立即恢复的重要文件,照片或视频.由于Root Android对于普通用户来说已成为一个相当复杂的过程,因此没有root的Android最佳恢复应用程序肯定 ...
最新文章
- 最深刻最通俗的HTTPS 原理详解,图文并茂
- Android+Java中使用Aes对称加密的工具类与使用
- html底部自动加载下一页,js页面滚动到底部时自动加载下一页数据
- 苹果侧边滑动返回_后置指纹、侧边指纹、屏幕指纹到底哪个更好用? 来讨论一下!...
- 【学堂在线数据挖掘:理论方法笔记】第一天(3.17)
- pic单片机c语言 程序,PIC单片机C语言编程教程(1)
- Microsoft微软官方Win10 visual c++(vc++2019)运行库下载
- Java开发手册(嵩山版)
- 什么思维是计算机科学的基础概念,计算思维的定义和特征是什么
- css设置字体颜色怎么设,css里面怎么设置字体颜色?
- Linux下获取cpu温度
- 家用 NAS 服务器(1)| 配置选择及准备
- Redis 可视化管理(AnotherRedisDesktopManager / Medis / redis-commander / RedisDesktopManager)
- video.js 实现视频只能后退,不能快进
- mysql5.7.10 64_mysql5.7.10win764安装
- mysql骚操作_关于MySQL的一些骚操作——提升正确性,抠点性能
- 高质量伪原创怎么做(文章做伪原创的方法有哪些)
- 实验2——指纹单模块实验
- RS232 1394和USB
- LGBMRegressor拟合函数官方文档