20
20
import static androidx .viewpager2 .widget .ViewPager2 .SCROLL_STATE_IDLE ;
21
21
import static androidx .viewpager2 .widget .ViewPager2 .SCROLL_STATE_SETTLING ;
22
22
23
+ import android .view .ViewTreeObserver ;
23
24
import androidx .recyclerview .widget .RecyclerView ;
24
25
import androidx .annotation .NonNull ;
25
26
import androidx .annotation .Nullable ;
39
40
* the mediator object, {@link #attach()} will link the TabLayout and the ViewPager2 together. When
40
41
* creating an instance of this class, you must supply an implementation of {@link
41
42
* TabConfigurationStrategy} in which you set the text of the tab, and/or perform any styling of the
42
- * tabs that you require. Changing ViewPager2's adapter will require a {@link #detach()} followed by
43
- * {@link #attach()} call. Changing the ViewPager2 or TabLayout will require a new instantiation of
43
+ * tabs that you require. Changing the ViewPager2 or TabLayout will require a new instantiation of
44
44
* TabLayoutMediator.
45
45
*/
46
46
public final class TabLayoutMediator {
@@ -54,6 +54,7 @@ public final class TabLayoutMediator {
54
54
55
55
@ Nullable private TabLayoutOnPageChangeCallback onPageChangeCallback ;
56
56
@ Nullable private TabLayout .OnTabSelectedListener onTabSelectedListener ;
57
+ @ Nullable private ViewPagerOnLayoutListener onLayoutListener ;
57
58
@ Nullable private RecyclerView .AdapterDataObserver pagerAdapterObserver ;
58
59
59
60
/**
@@ -127,6 +128,13 @@ public void attach() {
127
128
onTabSelectedListener = new ViewPagerOnTabSelectedListener (viewPager , smoothScroll );
128
129
tabLayout .addOnTabSelectedListener (onTabSelectedListener );
129
130
131
+ // Here we'll add a listener that responds to adapter changes. Unlike ViewPager,
132
+ // ViewPager2 doesn't have a built-in OnAdapterChangeListener, so we'll use a
133
+ // slightly different approach that relies on the fact that changing the adapter
134
+ // always causes a layout pass (see b/135299048).
135
+ onLayoutListener = new ViewPagerOnLayoutListener ();
136
+ viewPager .getViewTreeObserver ().addOnGlobalLayoutListener (onLayoutListener );
137
+
130
138
// Now we'll populate ourselves from the pager adapter, adding an observer if
131
139
// autoRefresh is enabled
132
140
if (autoRefresh ) {
@@ -151,8 +159,10 @@ public void detach() {
151
159
adapter .unregisterAdapterDataObserver (pagerAdapterObserver );
152
160
pagerAdapterObserver = null ;
153
161
}
162
+ viewPager .getViewTreeObserver ().removeOnGlobalLayoutListener (onLayoutListener );
154
163
tabLayout .removeOnTabSelectedListener (onTabSelectedListener );
155
164
viewPager .unregisterOnPageChangeCallback (onPageChangeCallback );
165
+ onLayoutListener = null ;
156
166
onTabSelectedListener = null ;
157
167
onPageChangeCallback = null ;
158
168
adapter = null ;
@@ -317,4 +327,16 @@ public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
317
327
populateTabsFromPagerAdapter ();
318
328
}
319
329
}
330
+
331
+ private class ViewPagerOnLayoutListener implements ViewTreeObserver .OnGlobalLayoutListener {
332
+
333
+ @ Override
334
+ public void onGlobalLayout () {
335
+ RecyclerView .Adapter <?> currentAdapter = viewPager .getAdapter ();
336
+ if (adapter != currentAdapter ) {
337
+ detach ();
338
+ attach ();
339
+ }
340
+ }
341
+ }
320
342
}
0 commit comments