4

我有一个包含 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会继续玩。有人可以让我知道我做错了什么吗?我在其他地方使用过这种模式(不是用 a VideoView),它成功地允许旋转发生。

我不愿意使用android:configChanges="keyboardHidden|orientation|screenSize"或类似的方法,我想用Fragments 处理方向变化。

预先感谢您的帮助。

编辑

我最终选择了我所做的解决方案,因为它有效。每次调用 onCreateView 时都需要重新创建 videoview 和控制器,并且需要在 onResume 中设置播放位置并在 onPause 中记录播放位置。但是,在旋转过程中播放是断断续续的。该解决方案不是最佳的,但它确实有效。

4

2 回答 2

2

请参阅mVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer);VideoView的活动是由在旋转时被销毁和重新创建的活动创建的。这意味着R.id.videoPlayer正在创建一个新的 VideoView。因此,您的本地mVideoPlayer只是在上面的行中被覆盖。您的片段需要VideoView在其 onCreateView() 方法中创建。即便如此,这可能还不够。因为视图本质上与它们拥有的上下文相关联。也许一个明确的暂停,检测和附加,视图的播放将是一个更好的方法。

于 2013-07-07T16:17:28.247 回答
0

以下是一些观察:

1.首先,您应该知道,即使保留了片段,活动也会被破坏。
结果,onCreate()每次都会调用添加片段的活动方法,从而导致多个片段相互重叠。

VideoPlayerActivity您需要一种机制来确定活动是第一次创建,还是由于配置更改而重新创建。
您可以通过将标志放入onSaveInstanceState()然后签入savedInstanceState来解决此问题onCreate()。如果为null,则表示activity是第一次创建,所以现在才可以添加fragment。

@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;
    }
   }
}

如果上述所有内容对您没有意义,请预留一些时间来玩片段,尤其是片段中的布局膨胀,然后再回来阅读这个答案。

于 2013-07-07T16:39:30.733 回答