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;
+ }
+ }
}