方向変更時にフラグメントを処理するフールプルーフな方法


87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

2つのリストビューを並べて表示する必要があります。左側にメニュー、右側にそのコンテンツを表示します。デフォルトでは、最初のメニューが選択され、その内容が右側に表示されます。コンテンツを表示するフラグメントは以下の通りです:

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

onActivityCreatedとonCreateViewは2回呼び出さます。フラグメントを使用した多くの例があります。私はこのテーマの初心者なので、この例と私の問題を関連付けることはできません。方向の変更を処理するための簡単な方法が必要です。android:configChangesマニフェストファイルで宣言していません。横向きモードで別のレイアウトを使用できるように、アクティビティを破棄して再作成する必要があります。


通常、フラグメントの向きの変更は、何もすることなく処理されます。では、向きを変えるとどのような問題が発生しますか?
Alexander Kulyakhtin

アレックス私は、クラスDetailPart1フラグメントを使用して、listViewのレイアウトを縦長モードで表示し、レイアウトをグリッドビューのレイアウトを横長モードで表示します。このため、毎回フラグメントを再作成する必要がありますが、同じレコードを再度ロードしたくないので、それらをonSaveInstanceStateに保存します。ただし、上記のコードはDetailPart1を2回再作成します。必要なコードを機能させるための欠落しているコードを知る必要があります
user1811741

回答:


132

アクティビティで画面をオンにするたびに新しいフラグメントを作成していますが、を使用してonCreate();古いフラグメントも維持していsuper.onCreate(savedInstanceState);ます。したがって、タグを設定してフラグメントが存在する場合はそれを見つけるか、またはnullバンドルをスーパーに渡します。

これは私が学ぶのにしばらくかかりました、そしてあなたがviewpagerのようなもので働いているとき、それは本当にbi ****でありえます。

この正確なトピックがカバーされているので、フラグメントについてもう一度読むことをお勧めします。

これは、通常の方向変更でフラグメントを処理する方法の例です。

活動

public class MainActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

フラグメント

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}

Warpzitの努力に感謝しますが、コードであなたのポイントについて説明していただければ嬉しいです。フラグメントをリロードせずに方向の変更を処理するようにコードを変更する方法
user1811741

1
したがって、方向に応じて変更するフラグメントのレイアウトが必要ですが、すべてのレコードをリロードしたくありません。何をしたか1.マニフェストにandroid:configchanges = "orientation"を追加2.フラグメントのonConfigurationChangedをオーバーライドして方向を検出方向に応じてリストビューまたはグリッドビューを非表示/表示します。これは正しい方法ですか?
user1811741

@ user1811741が例で更新されました。すべてが明確になることを願っています。
Warpzit

@Warpzit ViewPagerは表示されたすべてのフラグメントを処理するため、ViewPager Fragment実装の場合に同じシナリオをどのように処理できますか。
CoDe、2014

1
@Shubhまあ、そうでなければ、必要に応じてgetItem実装をオーバーライドする必要がある場合は、viewpagerがこれを適切に処理すると思います。適切な質問をしなければ、正しい方向にあなたを向けたと思います:)
Warpzit

21

向きの変更とアクティビティの再現の間にデータを保持する方法に関する適切なガイドラインは、Androidのガイドラインにあります。

概要:

  1. フラグメントを保持可能にします。

    setRetainInstance(true);
  2. 必要な場合にのみ新しいフラグメントを作成する(または少なくともフラグメントからデータを取得する)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {

nice時間を節約してください
Arjun saini
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.