首先思考以下幾個問題:
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中的布局參數;
上面的全屏動畫在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)分析開始。