【android】ViewPagerでタブ毎に戻れる画面を実装する方法
はじめに
今回やりたかったのはこんな画面。
なんでもiOSと比較するのはあれだけど、iOSだとUiNavigationControllerを持つUITabbarControllerみたいなイメージ。
今回はタブは表示していないけどViewPagerをタブ表示するサンプルはたくさんあるので問題なかった。
戻るボタンでの戻り先をタブごとに保持しているようなイメージ。
クラス構成としてはこんなイメージ。
Activityは1つでタブごとにRootFragmentを持たせて、実際に画面に表示するフラグメントを操作するイメージ(ここではFirstFragmentとSecondFragment)。
実装
MainActivityの実装
ここでやることはViewPagerとRootFragmentを紐づける処理。
あとは戻るボタンされた時に選択中のタブのバックスタックから1つ取り出して戻す処理。
戻るボタンされたときに選択中のタブがわかるようにタブ選択されるたびに選択中のタブ番号を保持する。
MainActivity.java
public class MainActivity extends AppCompatActivity { private ViewPager mPager; private String[] mTitles = {"タブ1", "タブ2"}; // 選択中のタブ番号を保持 private int selected; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setTitle("タブ1"); mPager = (ViewPager)findViewById(R.id.viewpager); mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { selected = position; setTitle(mTitles[position]); } ・・・ }); FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return RootFragment.newInstance(mTags[position]); } @Override public int getCount() { return 2; } ・・・ }; mPager.setAdapter(adapter); } // 戻るボタン @Override public void onBackPressed() { // 選択中のタブのRootFragmentにバックスタックがあれば戻る処理 FragmentManager fm = getSupportFragmentManager(); List<Fragment> fragments = fm.getFragments(); Fragment fragment = fragments.get(selected); FragmentManager fragmentManager = fragment.getChildFragmentManager(); if (0 < fragmentManager.getBackStackEntryCount()) { fragmentManager.popBackStack(); } } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" ・・・ /> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="@android:color/white" /> </RelativeLayout>
RootFragmentの実装
ここではFirstFragmentを表示するだけ。それならRootFragmentなんて不要と思って最初実装していた。
けど、ViewPagerの中のFragmentをreplaceしても中身がレイアウトの表示が変わらない問題に直面。で
http://www.pineappslab.com/post/fragments-viewpager/
ここの記事を発見。ここの通りにやらせていただきました。
RootFragment.java
public class RootFragment extends Fragment { public static RootFragment newInstance() { RootFragment fragment = new RootFragment(); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_root, container, false); FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.root_frame, FirstFragment.newInstance()); fragmentTransaction.commit(); return view; } }
fragment_root.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root_frame" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout>
FirstFragmentの実装
FirstFragment.java
public class FirstFragment extends Fragment { public static FirstFragment newInstance(String tag) { FirstFragment fragment = new FirstFragment(); Bundle args = new Bundle(); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_first, container, false); Button button = (Button) view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { FragmentTransaction fragmentTransaction = getParentFragment().getChildFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.root_frame, SecondFragment.newInstance()); fragmentTransaction.addToBackStack(); fragmentTransaction.commit(); } }); return view; } }
fragment_first.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10sp" android:text="FirstFragment" android:textSize="30sp"/> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffff00" android:text="次へ" android:textSize="18sp"/> </LinearLayout>
SecondFragmentは画面表示するだけだからいいかな。。。
おわりに
よくわからないで調べながらやってたからこの画面実装するポイントは他にもけっこうあるはずなんだけど出てこない。。。
もうちょっと内容を分割して整理した方が良さそう。以上です