简单ViewPager2内嵌Recycleview 并联动Tablayout


第一步,首先贴布局

首先贴上TabLayout布局

<com.google.android.material.tabs.TabLayout
android:id="@+id/tl_menu"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:scrollbars="none"
app:tabIndicator="@null"
app:tabMaxWidth="@dimen/dimen_170_dp"
app:tabMinWidth="@dimen/dimen_165_dp"
app:tabMode="scrollable"/>

其中 fillViewport 设置为true 才能横向拉满整个布局

tabIndicator  设置为 @null 清除下划线

tabMaxWidth和tabMinWidth 属性为自定义tab样式 设置tab间隔

然后贴上ViewPager2布局  这就简单很多,只是普通样式

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_menu"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="7.5"

android:background="@color/white"

android:scrollbars="vertical" />


第二步,然后给viewpager2 创建一个adapter

实际上viewpager2继承自recycleview,所以

MenuViewPagerAdapter extends RecyclerView.Adapter<MenuViewPagerAdapter.ViewHolder>
@NonNull
@Override

public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_menu_viewpager, parent, false);

ViewHolder holder = new ViewHolder(view);

return holder;

}

@Override

public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

menuAdapter = new MenuAdapter(menuAdapterData);

RecyclerView recyclerView = holder.rvMenu;
recyclerView.setVerticalScrollBarEnabled(true);
LinearLayoutManager layoutManager_menu = new LinearLayoutManager(context);
layoutManager_menu.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager_menu);

ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
recyclerView.setLayoutParams(params);

menuAdapter.setmOnItemClickListener((v, menuItem, position1) -> mOnItemClickListener.onItemClick(v, menuItem));
recyclerView.setAdapter(menuAdapter);


}

@Override

public int getItemCount() {

return 4;

}

其实在这个MenuViewPagerAdapter中,我们将创建viewpager中内嵌的recycleview

并且setVerticalScrollBarEnabled 设置纵向滑动

并且赋值一个纵向布局setLayoutManager

并且通过ViewGroup.LayoutParams 将recycleview设置为纵横全都MATCH_PARENT


第三步,接着给这个内嵌的recyclerView再设置一个adapter ----menuAdapter

menuAdapter 实际上就是recycleview的列表样式,并没有特别之处,不作赘述 


第四步,便可以创建并给viewpager2赋值这个menuViewPagerAdapter   
MenuViewPagerAdapter menuViewPagerAdapter = new MenuViewPagerAdapter(this, mOrderLists);
vpMenu.setAdapter(menuViewPagerAdapter);

vpMenu.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {

@Override

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

super.onPageScrolled(position, positionOffset, positionOffsetPixels);

}

@Override

public void onPageSelected(int position) {

super.onPageSelected(position);

tlMenu.selectTab(tlMenu.getTabAt(position));

}

@Override

public void onPageScrollStateChanged(int state) {

super.onPageScrollStateChanged(state);

}

});

接着便可以创建并给viewpager2赋值这个menuViewPagerAdapter 

并且在切换页面选择时 onPageSelected  同步tablayout的切换     tlMenu.selectTab(tlMenu.getTabAt(position));


第五步,对tab进行初始化,并且绑定监听器

最后我们初始化一个tab,并赋值text为饮料,然后加入到tablayout中

TabLayout.Tab tab1 = tlMenu.newTab();
tab1.setText("饮料");

tlMenu.addTab(tab1);
接着设置一个监听器,在tab切换的同时,对viewpager进行同步显示即可

tlMenu.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override

public void onTabSelected(TabLayout.Tab tab) {

View view = tab.getCustomView();

if (view != null) {

TextView textView = view.findViewById(R.id.tv_tab);

textView.setTextColor(getResources().getColor(R.color.menu_font_grey));

}

int position = tab.getPosition();

vpMenu.setCurrentItem(position);

}

@Override

public void onTabUnselected(TabLayout.Tab tab) {

View view = tab.getCustomView();

if (view != null) {

TextView textView = view.findViewById(R.id.tv_tab);

textView.setTextColor(getResources().getColor(R.color.white));

}

}

@Override

public void onTabReselected(TabLayout.Tab tab) {

}

});


最后,贴一段完全自定义tablayout中tab的代码
for (int i = 0; i < 4; i++) {
TabLayout.Tab tab = tlMenu.getTabAt(i);
if (tab != null) {
tab.setCustomView(R.layout.item_tab_view);
View view = tab.getCustomView();
if (view != null) {
TextView textView = view.findViewById(R.id.tv_tab);
textView.setText(tab.getText());
if (i % 2 == 0) {
textView.setBackgroundResource(R.drawable.tab_selector_single);
} else {
textView.setBackgroundResource(R.drawable.tab_selector_double);
}
if (i == 0) {
textView.setTextColor(getResources().getColor(R.color.menu_font_grey));
}
}
}
}

首先,我们有一个对tab的自定义文件item_tab_view,里面其实只是一个textview,进行了一些样式调整

通过setCustomView设置这个布局,然后马上通过getCustomView 获得这个布局view,然后找到其中的textview,并且设置tab原来的文本(此处不设置的话,其他地方设置的文本都会被自定义布局直接覆盖,导致一个字都没有)

通过setBackgroundResource 设置tab不同的显示样式

并且给第一个tab直接赋值文字颜色setTextColor,不然第一个tab的文字不会显示为点击选中的效果



贴效果图