ActionBarSherlockでActionBarとViewPagerを連携する
ActionBarSherlockのFragmentデモにあるTabs and Pagerは、OSネイティブのタブUIを使っているため2.3以前の端末で動かしたときと4.0以降で動かしたときで表示が異なります。
そこで、ActionBarのタブとViewPagerを連携することでどの端末でも見た目を統一できます。
ソースコード全体は以下に置きました。
ダミーFragmentの作成
各タブに表示するためのダミーFragmentを作ります。
public class DummyFragment extends SherlockFragment { private int mNum; public static DummyFragment getInstance(int num) { DummyFragment fragment = new DummyFragment(); Bundle args = new Bundle(); args.putInt("num", num); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = this.getArguments(); mNum = (args != null) ? args.getInt("num") : 0; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView view = (TextView) inflater.inflate(R.layout.hello_world, container, false); view.setText("Tab" + mNum); return view; } }
ダミーFragmentのXMLファイル(hello_world.xml)
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/hello_text" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical|center_horizontal" android:text="@string/hello_world" android:textAppearance="?android:attr/textAppearanceMedium" />
FragmentPagerAdapterの作成
ViewPagerを管理するためにFragmentPagerAdapterのサブクラス(TabAdapterクラス)を作ります。
ActionBarでタブを使えるようにするためにActionBar.NAVIGATION_MODE_TABSを設定します。
mViewPager.setOnPageChangeListener()で設定するイベントについては後述します。
public TabAdapter(SherlockFragmentActivity activity, ViewPager pager) { super(activity.getSupportFragmentManager()); mActionBar = activity.getSupportActionBar(); mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); mViewPager = pager; mViewPager.setOnPageChangeListener(mOnPageChangeListener); } @Override public Fragment getItem(int position) { TabInfo info = mTabs.get(position); if (info != null) { if (info.fragment == null) { info.fragment = DummyFragment.getInstance(position); } return info.fragment; } else { return new Fragment(); } } @Override public int getCount() { return this.mTabs.size(); }
タブの追加処理
タブを追加できるよう、TabAdapterクラスにメソッドを追加します。
setTabListener()で設定するイベントについては後述します。
private final SparseArray<TabInfo> mTabs = new SparseArray<TabInfo>(); public void addTab(String tag, Class<?> clazz, Bundle args) { ActionBar.Tab tab = this.mActionBar.newTab(); tab.setText(tag); tab.setTabListener(mTabListener); this.mActionBar.addTab(tab); TabInfo info = new TabInfo(tag, clazz, args); mTabs.put(tab.getPosition(), info); }
タブ情報の管理クラス(TabInfoクラス)以下のように定義しました。
static final class TabInfo { public final String tag; public final Class<?> clss; public final Bundle args; public Fragment fragment; TabInfo(String _tag, Class<?> _class, Bundle _args) { tag = _tag; clss = _class; args = _args; } }
タブ制御イベントの追加
ActionBarのタブをタップしたときの制御イベントを定義します。
ActionBarとViewPagerは別制御なので、タブを選択したときにViewPagerを選択するようonTabSelected()メソッドに処理を追加します。
private final ActionBar.TabListener mTabListener = new ActionBar.TabListener() { @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } };
次にViewPagerからActionBarを制御するための制御イベントを定義します。
ViewPagerのページが切り替わったらActionBarのタブも切り替わるようにonPageSelected()メソッドに処理を追加します。
private final ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { mActionBar.selectTab(mActionBar.getTabAt(position)); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { } };
Activityからの呼び出し
SherlockFragmentActivityのonCreateでタブの管理処理を呼び出します。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPager pager = (ViewPager) findViewById(R.id.pager); TabAdapter tabAdapter = new TabAdapter(this, pager); pager.setAdapter(tabAdapter); tabAdapter.addTab("Tab1", DummyFragment.class, null); tabAdapter.addTab("Tab2", DummyFragment.class, null); tabAdapter.addTab("Tab3", DummyFragment.class, null); }
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <FrameLayout android:id="@android:id/tabcontent" android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="0" /> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>
これでAndroid 4.0より前の端末でも4.0のようなTab+ViewPagerが使えるようになります。