最近項目中使用了android design包中得TabLayout+ViewPager,和大家分享一下我發(fā)現(xiàn)了一個的問題勋颖。當通過TabLayout.newTab之后,然后通過setupWithViewPager將TabLayout和ViewPager建立關(guān)聯(lián),這時會發(fā)現(xiàn)之前設(shè)置的tab消失了覆旱,具體的代碼和如何查找源碼解決見如何代碼:
- 示例代碼
mTl = (TabLayout) findViewById(R.id.id_tablayout);
mVp = (ViewPager) findViewById(R.id.id_vp);
//添加兩個tab
mTl.addTab(mTl.newTab().setText("登陸"));
mTl.addTab(mTl.newTab().setText("注冊"));
//讓tablayout與viewpager建立關(guān)聯(lián)關(guān)系
//mTl.setupWithViewPager(mVp);
mVp.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return 2;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
TextView textView = new TextView(container.getContext());
textView.setText("position:" + position);
container.addView(textView);
return textView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
});
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zeal.coordinatelayoutdemo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/id_tablayout"
android:layout_width="match_parent"
android:layout_height="50dip" />
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:id="@+id/id_vp"
android:layout_height="match_parent"></android.support.v4.view.ViewPager>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
上面的代碼運行之后,看起來好像沒有什么問題核无,但是我一滑動viewpager發(fā)現(xiàn)扣唱,viewpager是可以正常的滑動切換不同的view,但是頂部的tab并沒有跟著滑動团南。
- 解決viewpager與tablayout一起滑動
//讓tablayout與viewpager建立關(guān)聯(lián)關(guān)系
mTl.setupWithViewPager(mVp);
在tablayout中添加這段代碼噪沙,將viewpager與tablayout建立關(guān)聯(lián)。但是又發(fā)現(xiàn)一個問題吐根,我之前調(diào)用addTab(mTl.newTab().setText("登陸"))的兩個tab的數(shù)據(jù)呢正歼?怎么沒了?分析一下佑惠,我沒有對viewpager和tablayout建立關(guān)系時朋腋,不會有這個問題,一建立聯(lián)系就會出現(xiàn)問題膜楷,那么我們來瞅瞅mTl.setupWithViewPager(mVp);實現(xiàn)機制旭咽。
- 跟進源碼setupWithViewPager探究
//...省略一部分代碼
//處理從方法中傳入的viewpager
if (viewPager != null) {
mViewPager = viewPager;
//①以下這部分代碼是處理一些滑動的關(guān)聯(lián)關(guān)系。例如滑動監(jiān)聽
// Add our custom OnPageChangeListener to the ViewPager
if (mPageChangeListener == null) {
mPageChangeListener = new TabLayoutOnPageChangeListener(this);
}
mPageChangeListener.reset();
viewPager.addOnPageChangeListener(mPageChangeListener);
// Now we'll add a tab selected listener to set ViewPager's current item
mCurrentVpSelectedListener = new ViewPagerOnTabSelectedListener(viewPager);
addOnTabSelectedListener(mCurrentVpSelectedListener);
//②以下這部分代碼就可以解釋為什么我們的tab設(shè)置的內(nèi)容會不見了
final PagerAdapter adapter = viewPager.getAdapter();
if (adapter != null) {
// Now we'll populate ourselves from the pager adapter, adding an observer if
// autoRefresh is enabled
//將外部設(shè)置給viewpager的adapter取出來通過setPagerAdapter重新設(shè)置
setPagerAdapter(adapter, autoRefresh);
}
...
}
...
}
void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {
if (mPagerAdapter != null && mPagerAdapterObserver != null) {
// If we already have a PagerAdapter, unregister our observer
mPagerAdapter.unregisterDataSetObserver(mPagerAdapterObserver);
}
//注冊observer
mPagerAdapter = adapter;
if (addObserver && adapter != null) {
// Register our observer on the new adapter
if (mPagerAdapterObserver == null) {
mPagerAdapterObserver = new PagerAdapterObserver();
}
adapter.registerDataSetObserver(mPagerAdapterObserver);
}
// Finally make sure we reflect the new adapter
//關(guān)鍵代碼
populateFromPagerAdapter();
}
void populateFromPagerAdapter() {
//移除所有的tab
//我們之前設(shè)置的tab就是在這里被移除的
removeAllTabs();
if (mPagerAdapter != null) {
final int adapterCount = mPagerAdapter.getCount();
for (int i = 0; i < adapterCount; i++) {
//重新添加tab赌厅,而setText得內(nèi)容是在PagerAdapter中g(shù)etPageTitle獲取的穷绵,因此問題的答案就已經(jīng)很明顯了。 addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);
}
// Make sure we reflect the currently set ViewPager item
if (mViewPager != null && adapterCount > 0) {
final int curItem = mViewPager.getCurrentItem();
if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
selectTab(getTabAt(curItem));
}
}
}
}
- 修改代碼顯示tab內(nèi)容
在Adapter中復寫PagerAdapter中的getPageTitle方法就可以了特愿,看過上面的源碼可以知道在mVp和mTl建立聯(lián)系之后仲墨,會將設(shè)置給TabLayout的tab清除勾缭,并且重寫的創(chuàng)建,因此就沒有必要手動的去創(chuàng)建Tab了目养。
@Override
public CharSequence getPageTitle(int position) {
if(position ==0) {
return "登陸";
}else {
return "注冊";
}