类今日头条的滑动标签页效果核心由ViewPager+Fragment+TabLayout
三大组件构成。本文将深度解析各组件特性,并提供完整的实现方案。
// build.gradle(Module)
dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'com.google.android.material:material:1.9.0'
}
建议优先使用ViewPager2(支持垂直滑动和RTL布局),本文同时保留传统ViewPager实现方案。
1. 布局文件
2. 自定义PagerAdapter
public class NewsPagerAdapter extends PagerAdapter {
private final List mViews;
public NewsPagerAdapter(List views) {
mViews = views;
}
@Override
public int getCount() { return mViews.size(); }
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int pos) {
container.addView(mViews.get(pos));
return mViews.get(pos);
}
@Override
public void destroyItem(@NonNull ViewGroup container, int pos, @NonNull Object obj) {
container.removeView((View) obj);
}
}
3. Activity初始化
ViewPager viewPager = findViewById(R.id.viewPager);
List pages = new ArrayList<>();
// 添加通过LayoutInflater创建的View
viewPager.setAdapter(new NewsPagerAdapter(pages));
1. 创建Fragment基类
public class NewsFragment extends Fragment {
private static final String ARG_TITLE = "title";
public static NewsFragment newInstance(String title) {
NewsFragment frag = new NewsFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
frag.setArguments(args);
return frag;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 返回具体布局视图
}
}
2. FragmentPagerAdapter优化
public class FragmentAdapter extends FragmentPagerAdapter {
private final List fragments;
public FragmentAdapter(FragmentManager fm, List fragments) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.fragments = fragments;
}
@NonNull
@Override
public Fragment getItem(int pos) { return fragments.get(pos); }
@Override
public int getCount() { return fragments.size(); }
}
1. XML布局集成
2. 双向绑定实现
TabLayout tabLayout = findViewById(R.id.tabLayout);
ViewPager viewPager = findViewById(R.id.viewPager);
// 设置预加载页数(优化性能)
viewPager.setOffscreenPageLimit(3);
viewPager.setAdapter(adapter);
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
tab.setText(titles.get(position));
tab.setIcon(R.drawable.ic_tab_indicator);
}).attach();
3. 自定义Tab样式
viewPager.setPageTransformer(new DepthPageTransformer());
public class DepthPageTransformer implements ViewPager2.PageTransformer {
public void transformPage(View view, float position) {
if (position < -1) { // [-∞,-1]
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
view.setAlpha(1 + position);
view.setTranslationX(view.getWidth() * -position);
} else if (position <= 1) { // (0,1]
view.setAlpha(1 - position);
view.setTranslationX(view.getWidth() * -position);
} else { // (1,+∞]
view.setAlpha(0);
}
}
}
@Override
public void setUserVisibleHint(boolean isVisible) {
super.setUserVisibleHint(isVisible);
if (isVisible && isResumed()) {
loadData();
}
}
Fragment状态丢失
使用FragmentStatePagerAdapter
替代普通Adapter,自动处理Fragment生命周期。
TabLayout指示器错位
确保在ViewPager.setAdapter()之后调用TabLayout.setupWithViewPager()
滑动卡顿优化
RecyclerView.Adapter
代替传统Adapter