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誰かが私が間違っていることを教えてもらえますか? 私はこのパターンを他の場所で ( ではなくVideoView) 使用しており、回転を正常に行うことができます。

または同様の方法を使用したくありません。向きの変更をsandroid:configChanges="keyboardHidden|orientation|screenSize"で処理したいと思います。Fragment

よろしくお願いいたします。

編集

それが機能するため、私が行ったソリューションを選択することになりました。ビデオビューとコントローラーは、onCreateView が呼び出されるたびに再作成する必要があり、再生位置は onResume で設定し、onPause で記録する必要があります。ただし、回転中の再生は途切れ途切れです。解決策は最適ではありませんが、機能します。

4

2 に答える 2

2

参照してくださいmVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer); あなたVideoViewは、回転時に破棄され、再作成される活動によって作成されます。これは、新しいR.id.videoPlayerVideoView が作成されていることを意味します。したがって、ローカルmVideoPlayerは上記の行で上書きされています。フラグメントはVideoView、その onCreateView() メソッドで を作成する必要があります。それでも、これだけでは不十分な場合があります。ビューは本質的に所有するコンテキストにリンクされているためです。おそらく、明示的な一時停止、検出とアタッチ、ビューの再生がより良い方法でしょう。

于 2013-07-07T16:17:28.247 に答える
0

ここにいくつかの観察があります:

1.まず、フラグメントが保持されていても、アクティビティが破壊されることを知っておく必要があります。
その結果、onCreate()フラグメントを追加するアクティビティのメソッドが毎回呼び出されるため、複数のフラグメントが互いにオーバーラップします。

VideoPlayerActivityアクティビティが初めて作成されたのか、構成の変更によって再作成されたのかを判断するメカニズムが必要です。
この問題は、フラグを入れて in をチェックすることで解決できonSaveInstanceState()ます。null の場合は、アクティビティが初めて作成されたことを意味するため、フラグメントを追加できるのは今だけです。savedInstanceStateonCreate()

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

VideoPlayerActivityWorkerFragment2.次に、アクティビティで宣言されたものを参照していますVideoView

mVideoPlayer = (VideoView) mActivity.findViewById(R.id.videoPlayer);

画面を回転させると破壊されます。

あなたがすべきことは、それを抽出して、メソッドVideoViewのフラグメントによって膨張する別のレイアウト ファイルに入れることです。 しかし、ここでも問題が発生する可能性があります。呼び出されるという事実にもかかわらず、画面の向きで毎回呼び出されるため、レイアウトが再膨張します。onCreateView()
setRetainInstance(true)onCreateView()

解決策は、レイアウトをonCreateView()1 回だけインフレートすることです。

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 に答える