Activity 生成ウィザードの Tabbed Activity で Swipe Views(ViewPager)を選択して作成される Activity に付け足していきます。
*以下の例は minSdkVersion = 21 としています。
0. テーマに色をセット
メインカラーとアクセントカラーをセットしておきます
res/values-v21/styles.xml
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
- <item name="android:colorPrimaryDark">#00695C</item>
- <item name="android:colorPrimary">#00897B</item>
- <item name="android:colorAccent">#FFD54F</item>
- </style>
- </resources>

1. 普通に TabHost を実装する
- <?xml version="1.0" encoding="utf-8"?>
- <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">
- <TabHost
- android:id="@android:id/tabhost"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?android:attr/colorPrimary">
- <TabWidget
- android:id="@android:id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="0dp"
- android:layout_height="0dp" />
- </TabHost>
- <android.support.v4.view.ViewPager
- android:id="@+id/pager"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- // Create the adapter that will return a fragment for each of the three
- // primary sections of the activity.
- mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
- // Set up the ViewPager with the sections adapter.
- mViewPager = (ViewPager) findViewById(R.id.pager);
- mViewPager.setAdapter(mSectionsPagerAdapter);
- TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
- tabHost.setup();
- for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
- tabHost.addTab(tabHost
- .newTabSpec(String.valueOf(i))
- .setIndicator(mSectionsPagerAdapter.getPageTitle(i))
- .setContent(android.R.id.tabcontent));
- }
- tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
- @Override
- public void onTabChanged(String tabId) {
- mViewPager.setCurrentItem(Integer.valueOf(tabId));
- }
- });
- mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
- @Override
- public void onPageSelected(int position) {
- super.onPageSelected(position);
- tabHost.setCurrentTab(position);
- }
- });
- }

基本的なタブ機能が実装できましたが、Material Design に沿ったタブにするにはいくつか修正が必要です。
- タブ間の区切り線を消す
- Action Bar と タブの間の影を消す
- タブの下に影を出す
- タブの文字を仕様に合わせる
- ViewPager のスクロールに応じてインディケータもスクロールさせる
2. タブ間の区切り線を消す
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- TabWidget tabWidget = (TabWidget) findViewById(android.R.id.tabs);
- // タブ間の区切り線を消す
- tabWidget.setStripEnabled(false);
- tabWidget.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE);
- }

3. Action Bar と タブの間の影を消す
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- // Action Bar と タブの間の影を消す
- getActionBar().setElevation(0);
- }

4. タブの下に影を出す
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- // タブの下に影を出す
- // App bar の elevation は 4dp
- // http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html#objects-in-3d-space-elevation
- float elevation = 4 * getResources().getDisplayMetrics().density;
- tabHost.setElevation(elevation);
- }

5. タブの文字を仕様に合わせる
res/color/tab_widget_text.xml
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="#ffffffff" android:state_selected="true" />
- <item android:color="#99ffffff" />
- </selector>
- <?xml version="1.0" encoding="utf-8"?>
- <TextView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="bottom|center_horizontal"
- android:paddingBottom="16dp"
- android:textColor="@color/tab_widget_text"
- android:textSize="14sp"
- tools:layout_width="match_parent"
- tools:text="group 1 ITEM TWO" />
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- LayoutInflater inflater = LayoutInflater.from(this);
- for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
- TextView tv = (TextView) inflater.inflate(R.layout.tab_widget, tabWidget, false);
- tv.setText(mSectionsPagerAdapter.getPageTitle(i));
- tabHost.addTab(tabHost
- .newTabSpec(String.valueOf(i))
- .setIndicator(tv)
- .setContent(android.R.id.tabcontent));
- }
- ...
- }

6. ViewPager のスクロールに応じてインディケータもスクロールさせる
- <?xml version="1.0" encoding="utf-8"?>
- <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">
- <TabHost
- android:id="@android:id/tabhost"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?android:attr/colorPrimary">
- ...
- <View
- android:id="@+id/indicator"
- android:layout_width="match_parent"
- android:layout_height="2dp"
- android:layout_gravity="bottom"
- android:background="?android:attr/colorControlActivated" />
- </TabHost>
- ...
- </LinearLayout>
- View indicator;
- TabWidget tabWidget;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- tabWidget = (TabWidget) findViewById(android.R.id.tabs);
- ...
- indicator = findViewById(R.id.indicator);
- mViewPager.setOnPageChangeListener(new PageChangeListener());
- }
- private class PageChangeListener implements ViewPager.OnPageChangeListener {
- private int scrollingState = ViewPager.SCROLL_STATE_IDLE;
- @Override
- public void onPageSelected(int position) {
- // スクロール中はonPageScrolled()で描画するのでここではしない
- if (scrollingState == ViewPager.SCROLL_STATE_IDLE) {
- updateIndicatorPosition(position, 0);
- }
- tabWidget.setCurrentTab(position);
- }
- @Override
- public void onPageScrollStateChanged(int state) {
- scrollingState = state;
- }
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- updateIndicatorPosition(position, positionOffset);
- }
- private void updateIndicatorPosition(int position, float positionOffset) {
- View tabView = tabWidget.getChildTabViewAt(position);
- int indicatorWidth = tabView.getWidth();
- int indicatorLeft = (int) ((position + positionOffset) * indicatorWidth);
- final FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) indicator.getLayoutParams();
- layoutParams.width = indicatorWidth;
- layoutParams.setMargins(indicatorLeft, 0, 0, 0);
- indicator.setLayoutParams(layoutParams);
- }
- }

このコメントは投稿者によって削除されました。
返信削除SectionsPagerAdapterに、シンボルがありません。と出ます。どこで設定すればいいでしょうか?
返信削除