我有一个包含VideoView的简单布局。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/black"
android:gravity="center" >
<VideoView
android:id="@+id/videoPlayer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
使用此布局的Activity
会创建Fragment
以启动VideoView
public class VideoPlayerActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_player);
createNewWorkerFragment();
}
private void createNewWorkerFragment() {
FragmentManager fragmentManager = getFragmentManager();
VideoPlayerActivityWorkerFragment workerFragment = (VideoPlayerActivityWorkerFragment)fragmentManager.findFragmentByTag(VideoPlayerActivityWorkerFragment.Name);
if (workerFragment == null) {
workerFragment = new VideoPlayerActivityWorkerFragment();
fragmentManager.beginTransaction()
.add(workerFragment, VideoPlayerActivityWorkerFragment.Name)
.commit();
}
}
}
VideoPlayerActivityWorkerFragment
如下:
public class VideoPlayerActivityWorkerFragment extends Fragment {
public static String Name = "VideoPlayerActivityWorker";
private VideoView mVideoPlayer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer);
mVideoPlayer.setVideoPath(mActivity.getIntent().getExtras().getString("path"));
MediaController controller = new MediaController(mActivity);
controller.setAnchorView(mVideoPlayer);
mVideoPlayer.setMediaController(controller);
mVideoPlayer.requestFocus();
mVideoPlayer.start();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
}
这是我遇到的问题,当VideoPlayerActivity
开始创建VideoPlayerActivityWorkerFragment
并且VideoView
开始播放时,但是当我旋转设备时视频停止而不会玩,整个View
似乎从布局中消失了。由于setRetainInstance(true);
我认为VideoView
会继续播放。有人能让我知道我做错了什么吗?我在其他地方使用过这种模式(不是VideoView
),它成功地允许轮换发生。
我不愿意使用android:configChanges="keyboardHidden|orientation|screenSize"
或类似的方法,我想用Fragment
来处理方向更改。
提前感谢您的帮助。
我最终选择了我所做的解决方案,因为它有效。每次调用onCreateView时都需要重新创建视频视图和控制器,并且需要在onResume中设置播放位置并在onPause中重新播放。但是,在旋转期间播放是不稳定的。解决方案并非最佳,但确实有效。
答案 0 :(得分:2)
参见mVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer);
您的VideoView
是由正在销毁的活动创建的,并在轮换时重新创建。这意味着正在创建新的R.id.videoPlayer
VideoView。因此,您的本地mVideoPlayer
只是在您的上一行中被覆盖。您的片段需要在其onCreateView()方法中创建VideoView
。即便如此,这可能还不够。因为视图本身与其拥有的Context相关联。也许明确的暂停,检测和附加,播放视图将是一个更好的方法。
答案 1 :(得分:0)
以下是一些观察结果:
1.首先,您应该知道即使片段被保留,活动也会被破坏
因此,每次调用添加片段的onCreate()
活动方法,从而导致多个片段相互重叠。
在VideoPlayerActivity
中,您需要一种机制来确定活动是第一次创建,还是由于配置更改而重新创建。
您可以在onSaveInstanceState()
中放置一个标记然后检查savedInstanceState
中的onCreate()
来解决此问题。如果它为null,则表示活动是第一次创建的,所以现在只能添加片段。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState == null) {
createNewWorkerFragment();
}
}
// ....
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("fragment_added", true);
}
2.其次,在VideoPlayerActivityWorkerFragment
中,您引用了活动中声明的VideoView
:
mVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer);
在屏幕旋转时会被破坏。
你应该做的是提取VideoView
并将其放在一个单独的布局文件中,该文件将被onCreateView()
方法中的片段夸大。
但即使在这里你也可能遇到一些麻烦。推断调用setRetainInstance(true)
的事实,每次在屏幕方向调用onCreateView()
时,都会导致布局再次膨胀。
解决方案是仅在onCreateView()
中夸大布局一次:
public class VideoPlayerActivityWorkerFragment extends Fragment {
private View view;
//.....
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.my_video_view, container, false);
mVideoPlayer = (VideoView) view.findViewById(R.id.videoPlayer);
// .....
} else {
// If we are returning from a configuration change:
// "view" is still attached to the previous view hierarchy
// so we need to remove it and re-attach it to the current one
ViewGroup parent = (ViewGroup) view.getParent();
parent.removeView(view);
}
return view;
}
}
}
如果上面说的所有内容对你没有意义,请留出一些时间来播放片段,特别是片段中布局的膨胀,然后再回过头来阅读这个答案。