重学Android之View——TabLayoutMediator解析
1.前言
在使用TabLayout+ViewPager2+Fragment的时候,查询别人的使用例子,看到了
TabLayoutMediator这个类,撰写此文,仅当学习思考,本文是在引用material:1.7.0的版本基础上
2.测试效果
Tab + ViewPager2 + Fragment
3.内部成员变量介绍
public final class TabLayoutMediator {
@NonNull private final TabLayout tabLayout;
@NonNull private final ViewPager2 viewPager;
private final boolean autoRefresh;
private final boolean smoothScroll;
private final TabConfigurationStrategy tabConfigurationStrategy;
@Nullable private RecyclerView.Adapter<?> adapter;
private boolean attached;
@Nullable private TabLayoutOnPageChangeCallback onPageChangeCallback;
@Nullable private TabLayout.OnTabSelectedListener onTabSelectedListener;
@Nullable private RecyclerView.AdapterDataObserver pagerAdapterObserver;
......
TabLayoutMediator类引用了tabLayout跟ViewPager2对象,另外内部定义定义了tabLayout跟Viewpager2的
监听回调类,还有adapter关于数据的监听类
4.TabLayoutOnPageChangeCallback
这个是viewPager2的监听类,主要目的是,在viewPager2发生页面变化的时候,去同步更新TabLaout的状态
,通过使用如下TabLaout的Api去更新tabLayout的状态
tabLayout.selectTab()
tabLayout.setScrollPosition()
并且通过如下方法,注册到viewPager的监听器中
viewPager.registerOnPageChangeCallback();
具体的ViewPager2.OnPageChangeCallback的监听类,在这里不仔细介绍
private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
@NonNull private final WeakReference<TabLayout> tabLayoutRef;
private int previousScrollState;
private int scrollState;
TabLayoutOnPageChangeCallback(TabLayout tabLayout) {
tabLayoutRef = new WeakReference<>(tabLayout);
reset();
}
@Override
public void onPageScrollStateChanged(final int state) {
previousScrollState = scrollState;
scrollState = state;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
TabLayout tabLayout = tabLayoutRef.get();
if (tabLayout != null) {
// Only update the text selection if we're not settling, or we are settling after
// being dragged
boolean updateText =
scrollState != SCROLL_STATE_SETTLING || previousScrollState == SCROLL_STATE_DRAGGING;
// Update the indicator if we're not settling after being idle. This is caused
// from a setCurrentItem() call and will be handled by an animation from
// onPageSelected() instead.
boolean updateIndicator =
!(scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
tabLayout.setScrollPosition(position, positionOffset, updateText, updateIndicator);
}
}
@Override
public void onPageSelected(final int position) {
TabLayout tabLayout = tabLayoutRef.get();
if (tabLayout != null
&& tabLayout.getSelectedTabPosition() != position
&& position < tabLayout.getTabCount()) {
// Select the tab, only updating the indicator if we're not being dragged/settled
// (since onPageScrolled will handle that).
boolean updateIndicator =
scrollState == SCROLL_STATE_IDLE
|| (scrollState == SCROLL_STATE_SETTLING
&& previousScrollState == SCROLL_STATE_IDLE);
tabLayout.selectTab(tabLayout.getTabAt(position), updateIndicator);
}
}
void reset() {
previousScrollState = scrollState = SCROLL_STATE_IDLE;
}
}
5.ViewPagerOnTabSelectedListener
这个是TabLayout的监听类,主要目的是,在TabLayout发生页面变化的时候,去同步更新ViewPager2的状态
主要通过ViewPager2的Api,来更新状态viewPager2的状态
viewPager.setCurrentItem
通过tabLayout的addOnTabSelectedListener 方法来添加监听
tabLayout.addOnTabSelectedListener()
private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
private final ViewPager2 viewPager;
private final boolean smoothScroll;
ViewPagerOnTabSelectedListener(ViewPager2 viewPager, boolean smoothScroll) {
this.viewPager = viewPager;
this.smoothScroll = smoothScroll;
}
@Override
public void onTabSelected(@NonNull TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition(), smoothScroll);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
}
6.ViewPagerOnTabSelectedListener
通过viewPager2的适配器监听类来更新的tabLayout状态
private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {
PagerAdapterObserver() {}
@Override
public void onChanged() {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
populateTabsFromPagerAdapter();
}
}中
从上面的ViewPager2的适配器监听 ,收到数据的变化,就去更新tabLayout 状态,调用populateTabsFromPagerAdapter 函数
主要是根据数据的条目,更新tab的数量,然后,添加到tabLayout 中,注意,在这里通过接口回调的方式,回调了onConfigureTab方法,
调用者,就能够得到里面的tab的相关信息文章来源:https://www.toymoban.com/news/detail-423958.html
@SuppressWarnings("WeakerAccess")
void populateTabsFromPagerAdapter() {
tabLayout.removeAllTabs();
if (adapter != null) {
int adapterCount = adapter.getItemCount();
for (int i = 0; i < adapterCount; i++) {
TabLayout.Tab tab = tabLayout.newTab();
tabConfigurationStrategy.onConfigureTab(tab, i);
tabLayout.addTab(tab, false);
}
// Make sure we reflect the currently set ViewPager item
if (adapterCount > 0) {
int lastItem = tabLayout.getTabCount() - 1;
int currItem = Math.min(viewPager.getCurrentItem(), lastItem);
if (currItem != tabLayout.getSelectedTabPosition()) {
tabLayout.selectTab(tabLayout.getTabAt(currItem));
}
}
}
}
7.结合ViewPager2跟TabLayout
在这里去注册viewPager2跟Tablayout的各种监听,以及去初始化填充文章来源地址https://www.toymoban.com/news/detail-423958.html
public void attach() {
if (attached) {
throw new IllegalStateException("TabLayoutMediator is already attached");
}
adapter = viewPager.getAdapter();
if (adapter == null) {
throw new IllegalStateException(
"TabLayoutMediator attached before ViewPager2 has an " + "adapter");
}
attached = true;
// Add our custom OnPageChangeCallback to the ViewPager
onPageChangeCallback = new TabLayoutOnPageChangeCallback(tabLayout);
viewPager.registerOnPageChangeCallback(onPageChangeCallback);
// Now we'll add a tab selected listener to set ViewPager's current item
onTabSelectedListener = new ViewPagerOnTabSelectedListener(viewPager, smoothScroll);
tabLayout.addOnTabSelectedListener(onTabSelectedListener);
// Now we'll populate ourselves from the pager adapter, adding an observer if
// autoRefresh is enabled
if (autoRefresh) {
// Register our observer on the new adapter
pagerAdapterObserver = new PagerAdapterObserver();
adapter.registerAdapterDataObserver(pagerAdapterObserver);
}
populateTabsFromPagerAdapter();
// Now update the scroll position to match the ViewPager's current item
tabLayout.setScrollPosition(viewPager.getCurrentItem(), 0f, tru
8.外界使用TabLayoutMediator的简单调用事例
adapter = new ViewPagerFragmentAdapter(this, labels);
viewPager2.setAdapter(adapter);
TabLayoutMediator mediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
tab.setText(labels[position]);
}
});
viewPager2.setCurrentItem(2, false);
mediator.attach();
到了这里,关于重学Android之View——TabLayoutMediator解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!