在同一个activity的两个fragment里都有一个SurfaceView会导致后来显示的SurfaceView位置不对。
尝试过固定SurfaceView的大小,固定宽高等方法无效。
我就直接说方法吧
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
isHidden = hidden;
if (hidden) {
mSurfaceView.setVisibility(View.GONE);
release();
} else {
play();
}
}
就是在fragment影藏的时候SurfaceView设置GONE就行了。显示的时候在初始化一次这样就可以避免第二加载的fragment位置错位。
经过测试发现,仅仅
setVisibility(View.GONE);
有的时候还是会导致位置错乱;
后来查了资料才知道,SurfaceView
是在windows
层显示的,仅仅用View层的方法并不能控制SurfaceView
的生命周期,后来同事提示,既然显示隐藏不行那可以试试removeView
,然后尝试了一下,果然可以。
解决办法:在需要播放视频的位置外层嵌套一个layout,这里我用的
FrameLayout
,在释放的时候使用removeAllViews
,下面代码
/**
* 释放资源
*/
private void release() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
if (mSurfaceView != null && mSurfaceView.getHolder() != null && mSurfaceView.getHolder().getSurface() != null) {
mSurfaceView.getHolder().getSurface().release();
if (mSurfaceHolder != null && mEquipmentVideoCallBack != null) {
mSurfaceHolder.removeCallback(mEquipmentVideoCallBack);
mSurfaceHolder = null;
}
}
boxFrameLayout.removeAllViews();
}
需要注意的是,只要界面不在前台或者失去焦点的时候都需要释放一次,还有每次重新播放前也需要释放一次,重新进入准备状态。
主要有三个地方:
//第 1个.显示个隐藏的时候
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
}
//第2个从新获取焦点到前台
@Override
public void onResume() {
super.onResume();
}
// 第 3个播放完成后
MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
};
// 第 4个在onStop也需要释放次资源