diff --git a/src/android/support/design/widget/TabLayout.java b/src/android/support/design/widget/TabLayout.java index 9922c9448..3f7a5651f 100755 --- a/src/android/support/design/widget/TabLayout.java +++ b/src/android/support/design/widget/TabLayout.java @@ -85,10 +85,6 @@ import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING; * * You should set a listener via {@link #setOnTabSelectedListener(OnTabSelectedListener)} to be * notified when any tab's selection state has been changed. - *

- * If you're using a {@link android.support.v4.view.ViewPager} together - * with this layout, you can use {@link #setupWithViewPager(ViewPager)} to link the two together. - * This layout will be automatically populated from the {@link PagerAdapter}'s page titles.

* *

You can also add items to TabLayout in your layout through the use of {@link TabItem}. * An example usage is like so:

@@ -107,6 +103,28 @@ import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING; * </android.support.design.widget.TabLayout> * * + *

ViewPager integration

+ *

+ * If you're using a {@link android.support.v4.view.ViewPager} together + * with this layout, you can call {@link #setupWithViewPager(ViewPager)} to link the two together. + * This layout will be automatically populated from the {@link PagerAdapter}'s page titles.

+ * + *

+ * This view also supports being used as part of a ViewPager's decor, and can be added + * directly to the ViewPager in a layout resource file like so:

+ * + *
+ * <android.support.v4.view.ViewPager
+ *     android:layout_width="match_parent"
+ *     android:layout_height="match_parent">
+ *
+ *     <android.support.design.widget.TabLayout
+ *         android:layout_width="match_parent"
+ *         android:layout_height="wrap_content"
+ *         android:layout_gravity="top" />
+ *
+ * </android.support.v4.view.ViewPager>
+ * 
* * @see Tabs * @@ -121,6 +139,7 @@ import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING; * @attr ref android.support.design.R.styleable#TabLayout_tabMaxWidth * @attr ref android.support.design.R.styleable#TabLayout_tabTextAppearance */ +@ViewPager.DecorView public class TabLayout extends HorizontalScrollView { private static final int DEFAULT_HEIGHT_WITH_TEXT_ICON = 72; // dps @@ -251,6 +270,8 @@ public class TabLayout extends HorizontalScrollView { private PagerAdapter mPagerAdapter; private DataSetObserver mPagerAdapterObserver; private TabLayoutOnPageChangeListener mPageChangeListener; + private AdapterChangeListener mAdapterChangeListener; + private boolean mSetupViewPagerImplicitly; // Pool we use as a simple RecyclerBin private final Pools.Pool mTabViewPool = new Pools.SimplePool<>(12); @@ -741,9 +762,19 @@ public class TabLayout extends HorizontalScrollView { * content changes */ public void setupWithViewPager(@Nullable final ViewPager viewPager, boolean autoRefresh) { - if (mViewPager != null && mPageChangeListener != null) { + setupWithViewPager(viewPager, autoRefresh, false); + } + + private void setupWithViewPager(@Nullable final ViewPager viewPager, boolean autoRefresh, + boolean implicitSetup) { + if (mViewPager != null) { // If we've already been setup with a ViewPager, remove us from it - mViewPager.removeOnPageChangeListener(mPageChangeListener); + if (mPageChangeListener != null) { + mViewPager.removeOnPageChangeListener(mPageChangeListener); + } + if (mAdapterChangeListener != null) { + mViewPager.removeOnAdapterChangeListener(mAdapterChangeListener); + } } if (mCurrentVpSelectedListener != null) { @@ -753,11 +784,6 @@ public class TabLayout extends HorizontalScrollView { } if (viewPager != null) { - final PagerAdapter adapter = viewPager.getAdapter(); - if (adapter == null) { - throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set"); - } - mViewPager = viewPager; // Add our custom OnPageChangeListener to the ViewPager @@ -771,9 +797,19 @@ public class TabLayout extends HorizontalScrollView { mCurrentVpSelectedListener = new ViewPagerOnTabSelectedListener(viewPager); addOnTabSelectedListener(mCurrentVpSelectedListener); - // Now we'll populate ourselves from the pager adapter, adding an observer is - // autoRefresh is enabled - setPagerAdapter(adapter, autoRefresh); + final PagerAdapter adapter = viewPager.getAdapter(); + if (adapter != null) { + // Now we'll populate ourselves from the pager adapter, adding an observer if + // autoRefresh is enabled + setPagerAdapter(adapter, autoRefresh); + } + + // Add a listener so that we're notified of any adapter changes + if (mAdapterChangeListener == null) { + mAdapterChangeListener = new AdapterChangeListener(); + } + mAdapterChangeListener.setAutoRefresh(autoRefresh); + viewPager.addOnAdapterChangeListener(mAdapterChangeListener); // Now update the scroll position to match the ViewPager's current item setScrollPosition(viewPager.getCurrentItem(), 0f, true); @@ -783,6 +819,8 @@ public class TabLayout extends HorizontalScrollView { mViewPager = null; setPagerAdapter(null, false); } + + mSetupViewPagerImplicitly = implicitSetup; } /** @@ -801,6 +839,33 @@ public class TabLayout extends HorizontalScrollView { return getTabScrollRange() > 0; } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (mViewPager == null) { + // If we don't have a ViewPager already, check if our parent is a ViewPager to + // setup with it automatically + final ViewParent vp = getParent(); + if (vp instanceof ViewPager) { + // If we have a ViewPager parent and we've been added as part of its decor, let's + // assume that we should automatically setup to display any titles + setupWithViewPager((ViewPager) vp, true, true); + } + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mSetupViewPagerImplicitly) { + // If we've been setup with a ViewPager implicitly, let's clear out any listeners, etc + setupWithViewPager(null); + mSetupViewPagerImplicitly = false; + } + } + private int getTabScrollRange() { return Math.max(0, mTabStrip.getWidth() - getWidth() - getPaddingLeft() - getPaddingRight()); @@ -2111,4 +2176,19 @@ public class TabLayout extends HorizontalScrollView { } } + private class AdapterChangeListener implements ViewPager.OnAdapterChangeListener { + private boolean mAutoRefresh; + + @Override + public void onAdapterChanged(@NonNull ViewPager viewPager, + @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter) { + if (mViewPager == viewPager) { + setPagerAdapter(newAdapter, mAutoRefresh); + } + } + + void setAutoRefresh(boolean autoRefresh) { + mAutoRefresh = autoRefresh; + } + } }