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>
res/layout/tab_widget.xml
<?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に、シンボルがありません。と出ます。どこで設定すればいいでしょうか?
返信削除