GsyVideoPlayer视频分析(三)------------全屏实现

首先思考以下几个问题:

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) ; }
  gsyVideoPlayer.setIfCurrentIsFullscreen( true) ; gsyVideoPlayer.getFullscreenButton().setImageResource( gsyVideoPlayer.getShrinkImageRes()) ;//替换全屏按钮的图片为退出全屏的图片 gsyVideoPlayer.getBackButton().setVisibility(View. VISIBLE) ; //初始化旋转工具 orientationUtils = new OrientationUtils((Activity) context , gsyVideoPlayer) ; orientationUtils.setEnable(isAutoRotation()) ; gsyVideoPlayer.getBackButton().setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { resolveMaterialToNormal( gsyVideoPlayer) ;//设置退出全屏监听 } }) ; if ( showFullAnimation) { if ( fullViewContainer instanceof FrameLayout) { //目前只做了frameLoayout的判断 resolveMaterialAnimation() ; } else { resolveFullAdd() ; } } else { resolveFullAdd() ; }} 如果设置的需要显示动画且当前的容器是FrameLayout就执行resolveMaterialAnimation();

否则执行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中的布局参数;

GsyVideoPlayer视频分析(三)------------全屏实现_第1张图片


上面的全屏动画在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)分析开始。



你可能感兴趣的:(框架源码分析)