首先思考以下几个问题:
1.点击全屏按钮,视频是怎么填充整个屏幕的?(以及视频放大时的动画效果实现)
2.视频填充屏幕后,又是如何实现横屏的?
3.视频是如何做到,列表中的视频和放大后的视频,无缝衔接的?
依旧通过代码分析:
//设置全屏按键功能 gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resolveFullBtn(); } });全屏按钮由一个点击事件触发
public void resolveFullBtn() { if (fullViewContainer == null) { return; } if (!isFull) { resolveToFull(); } else { resolveMaterialToNormal(gsyVideoPlayer); } }fullViewContain是在ListVideoUtil初始化的时候设置的,具体分析可以查看 http://blog.csdn.net/qq_15631341/article/details/74332254
代码的意思是:
如果当前不是全屏,走resolveToFull;
如果当前是全屏,走resolveMaterialToNormal;
我们先分析展示全屏的过程,
/** * 处理全屏逻辑 */ private void resolveToFull() { systemUiVisibility = ((Activity) context).getWindow().getDecorView().getSystemUiVisibility(); CommonUtil.hideSupportActionBar(context, hideActionBar, hideStatusBar);//根据需求隐藏actionbar和statusbar if (hideKey) { hideNavKey(context); } isFull = true; //将gsyVideoplayer从原来的容器中剥离,即gsyVideoPlayer不在显示在ListView的摸一个item上了 ViewGroup viewGroup = (ViewGroup) gsyVideoPlayer.getParent();
//此处需要注意,gsyvideo还没有从listview的item上移除时,保存了当前的布局信息,用于后面动画的展示
listParams =
gsyVideoPlayer.getLayoutParams()
;
if (viewGroup !=
null) {
listParent = viewGroup
;
viewGroup.removeView(
gsyVideoPlayer)
;
}
否则执行resolveFullAdd()方法;即这两种方法的区别是一个是有动画效果的,一个是无动画效果的;
先来看一下没有动画效果的是如何实现的?
/** * 添加到全屏父布局里 */ private void resolveFullAdd() { fullViewContainer.setBackgroundColor(Color.BLACK); fullViewContainer.addView(gsyVideoPlayer); resolveChangeFirstLogic(50); }就是把一开始设置的fullViewContain的背景改为黑色,再把gsyVideoPlayer的布局添加进来,最后执行resolveChangeFirstLogic(50)方法;
再来看一下有动画效果的是 如何实现的?
/** * 如果是5.0的动画开始位置 */ private void resolveMaterialAnimation() { listItemRect = new int[2]; listItemSize = new int[2]; saveLocationStatus(context, hideStatusBar, hideActionBar);//保存gsyvideoplayer在listview的item中的位置和大小 FrameLayout.LayoutParams lpParent = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); FrameLayout frameLayout = new FrameLayout(context); frameLayout.setBackgroundColor(Color.BLACK); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(listItemSize[0], listItemSize[1]); lp.setMargins(listItemRect[0], listItemRect[1], 0, 0); frameLayout.addView(gsyVideoPlayer, lp); fullViewContainer.addView(frameLayout, lpParent); handler.postDelayed(new Runnable() { @Override public void run() { //开始动画 TransitionManager.beginDelayedTransition(fullViewContainer); resolveMaterialFullVideoShow(gsyVideoPlayer); resolveChangeFirstLogic(600); } }, 300); }
/** * 保存大小和状态 */ private void saveLocationStatus(Context context, boolean statusBar, boolean actionBar) { listParent.getLocationOnScreen(listItemRect);//获取listView中的gsyvideoplayer相对于屏幕的左边距和上边距并存入listItemRect中 int statusBarH = getStatusBarHeight(context); int actionBerH = getActionBarHeight((Activity) context); if (statusBar) { listItemRect[1] = listItemRect[1] - statusBarH; } if (actionBar) { listItemRect[1] = listItemRect[1] - actionBerH; } listItemSize[0] = listParent.getWidth(); listItemSize[1] = listParent.getHeight(); }listParent是在resolveToFull中保存的gsyvideoplayer在listView的item中的布局参数;
上面的全屏动画在handler的post方法之前,先构造了左边这个布局,listItemRect标注反了,需要互换一下,不好意思,不会画图,将就一下,并把它加入到fullViewContain中;只不过因为demo中的左右边距都为0,所以listItemRect[0]就是0,listItemRect[1]就是上边距再加上statusbar和actionbar的高度
/** * 如果是5.0的,要从原位置过度到全屏位置 */ private void resolveMaterialFullVideoShow(GSYBaseVideoPlayer gsyVideoPlayer) { FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) gsyVideoPlayer.getLayoutParams(); lp.setMargins(0, 0, 0, 0); lp.height = ViewGroup.LayoutParams.MATCH_PARENT; lp.width = ViewGroup.LayoutParams.MATCH_PARENT; lp.gravity = Gravity.CENTER; gsyVideoPlayer.setLayoutParams(lp); gsyVideoPlayer.setIfCurrentIsFullscreen(true); }在resolveMaterialFullVideoShow方法执行后,变为右边那张图;
至于中间的动画效果:只要
TransitionManager.beginDelayedTransition(fullViewContainer);
科普1:
要改变某个控件的位置,可以用修改布局参数后setLayoutParams,如果想给这个过程加上动画效果,则可以在父节点上调用TransitionManager.beginDelayedTransition
无论是resolveToFull还是resolveMaterialToNormal至此已经完成了全屏变化;两个方法最后都调用了resolveChangeFirstLogic
/** * 是否全屏一开始马上自动横屏 */ private void resolveChangeFirstLogic(int time) { if (isFullLandFrist()) { handler.postDelayed(new Runnable() { @Override public void run() { if (orientationUtils.getIsLand() != 1) { orientationUtils.resolveByClick(); } } }, time); } gsyVideoPlayer.setIfCurrentIsFullscreen(true); if (videoAllCallBack != null) { Debuger.printfLog("onEnterFullscreen"); videoAllCallBack.onEnterFullscreen(this.url); } }该方法是用来实现全屏后的屏幕旋转;
/** * 点击切换的逻辑,比如竖屏的时候点击了就是切换到横屏不会受屏幕的影响 */ public void resolveByClick() { mClick = true; if (mIsLand == 0) { screenType = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); gsyVideoPlayer.getFullscreenButton().setImageResource(gsyVideoPlayer.getShrinkImageRes()); mIsLand = 1; mClickLand = false; } else { screenType = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); if (gsyVideoPlayer.isIfCurrentIsFullscreen()) { gsyVideoPlayer.getFullscreenButton().setImageResource(gsyVideoPlayer.getShrinkImageRes()); } else { gsyVideoPlayer.getFullscreenButton().setImageResource(gsyVideoPlayer.getEnlargeImageRes()); } mIsLand = 0; mClickPort = false; } }这一块代码病史很难,就是横屏设置Activity为竖屏,竖屏就设置Activity为横屏;
最后解释一下,从列表视频到全屏视频的过程中,无缝衔接了,原因就是,只是GsyVideoPlayer这个布局换了一个父控件,GsyVideoManager中的medieplayer并没有停止播放,所以视频无缝衔接了。
最后留一个问题,大家自己思考吧,如何从全屏再回到列表视频????
从resolveMaterialToNormal(gsyVideoPlayer)分析开始。