基于单个RecyclerView实现TabLayout+ViewPager的数据切换需求
实现TabLayout+ViewPager联动并复用RecyclerView切换数据
1. 编写布局文件
主布局(activity_main.xml)
顶部放置TabLayout,下方是承载RecyclerView的ViewPager:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed" app:tabGravity="fill"/> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
ViewPager的页面容器(item_recycler_container.xml)
仅包含一个RecyclerView,用于后续复用:
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent"/>
2. 实现ViewPager适配器
核心逻辑是只初始化一次RecyclerView,切换Tab时仅更新数据:
public class RecyclerPagerAdapter extends PagerAdapter { private Context mContext; private List<String> mTabTitles; private RecyclerView mRecyclerView; private RecyclerAdapter mAdapter; private List<List<String>> mDataList; private ViewPager mViewPager; public RecyclerPagerAdapter(Context context, List<String> tabTitles, List<List<String>> dataList) { mContext = context; mTabTitles = tabTitles; mDataList = dataList; } @Override public int getCount() { return mTabTitles.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { // 仅初始化一次RecyclerView实例 if (mRecyclerView == null) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_recycler_container, container, false); mRecyclerView = view.findViewById(R.id.recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); mAdapter = new RecyclerAdapter(); mRecyclerView.setAdapter(mAdapter); // 监听RecyclerView滑动,到达边界时切换ViewPager页面 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); if (layoutManager == null) return; // 滑到顶部,切换上一个Tab if (dy < 0 && layoutManager.findFirstCompletelyVisibleItemPosition() == 0) { if (mViewPager.getCurrentItem() > 0) { mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1, true); } } // 滑到底部,切换下一个Tab else if (dy > 0 && layoutManager.findLastCompletelyVisibleItemPosition() == mAdapter.getItemCount() - 1) { if (mViewPager.getCurrentItem() < getCount() - 1) { mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, true); } } } }); container.addView(view); return view; } // 复用已有RecyclerView,直接更新数据 updateData(position); return mRecyclerView; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { // 因需要复用,此处不执行销毁操作 } @Nullable @Override public CharSequence getPageTitle(int position) { return mTabTitles.get(position); } // 更新RecyclerView数据的方法 public void updateData(int position) { if (mAdapter != null && position < mDataList.size()) { mAdapter.setData(mDataList.get(position)); } } public void setViewPager(ViewPager viewPager) { mViewPager = viewPager; } }
3. 实现RecyclerView适配器
简单的列表适配器,支持数据刷新:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> { private List<String> mData = new ArrayList<>(); public void setData(List<String> data) { mData.clear(); mData.addAll(data); notifyDataSetChanged(); } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { holder.tvContent.setText(mData.get(position)); } @Override public int getItemCount() { return mData.size(); } static class ViewHolder extends RecyclerView.ViewHolder { TextView tvContent; public ViewHolder(@NonNull View itemView) { super(itemView); tvContent = itemView.findViewById(android.R.id.text1); } } }
4. 主Activity绑定逻辑
初始化控件,完成联动配置和数据填充:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TabLayout tabLayout = findViewById(R.id.tabLayout); ViewPager viewPager = findViewById(R.id.viewPager); // 模拟Tab标题和对应数据集合 List<String> tabTitles = Arrays.asList("Tab1", "Tab2", "Tab3"); List<List<String>> dataList = new ArrayList<>(); dataList.add(generateData("Tab1数据")); dataList.add(generateData("Tab2数据")); dataList.add(generateData("Tab3数据")); RecyclerPagerAdapter adapter = new RecyclerPagerAdapter(this, tabTitles, dataList); adapter.setViewPager(viewPager); viewPager.setAdapter(adapter); tabLayout.setupWithViewPager(viewPager); // 监听ViewPager页面切换,更新数据并将RecyclerView滚到顶部 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageSelected(int position) { adapter.updateData(position); if (adapter.mRecyclerView != null) { adapter.mRecyclerView.scrollToPosition(0); } } @Override public void onPageScrollStateChanged(int state) {} }); } // 生成模拟数据的工具方法 private List<String> generateData(String prefix) { List<String> data = new ArrayList<>(); for (int i = 1; i <= 20; i++) { data.add(prefix + " - " + i); } return data; } }
核心逻辑说明
- 复用RecyclerView:ViewPager适配器仅创建一次RecyclerView实例,切换Tab时只更新列表数据,避免重复创建视图浪费资源。
- Tab与ViewPager联动:通过
tabLayout.setupWithViewPager(viewPager)快速实现点击Tab切换页面、滑动ViewPager同步Tab选中状态的效果。 - 滑动RecyclerView切数据:给RecyclerView添加滑动监听,当滑到列表顶部/底部时,自动触发ViewPager切换页面,进而更新RecyclerView展示的数据。
内容的提问来源于stack exchange,提问作者mobin jafari
相关产品推荐
相关产品推荐

