ViewPager2最显著的特点是基于RecyclerView实现,RecyclerView是目前Android端最成熟的AdapterView解决方案,这带来诸多好处:
1、抛弃传统的PagerAdapter,统一了Adapter的API/
2、通过LinearLayoutManager可以实现类似抖音的纵向滑动
3、支持DiffUitl,可以通过diff实现局部刷新
4、支持RTL(right-to-left)布局,对于一些有出海需求的APP非常有用
5、支持ItemDecorator
一、ViewPager2和ViewPager的对比:
1、ViewPager2内部实现是RecyclerView,所以ViewPager2的性能更高。
2、ViewPager2可以实现竖向滑动,ViewPager只能横向滑动。
3、ViewPager2只有一个adapter,FragmentStateAdapter继承自RecyclerView.Adapter。
而ViewPager有两个adapter,FragmentStatePagerAdapter和FragmentPagerAdapter,均是继承PagerAdapter。FragmentStatePagerAdapter和FragmentPagerAdapter两者的区别是FragmentStatePagerAdapter不可以缓存,FragmentPagerAdapter可以缓存。
4、ViewPager2模式实现了懒加载,默认不进行预加载。内部是通过Lifecycle 对 Fragment 的生命周期进行管理。ViewPager会进行预加载,懒加载需要我们自己去实现。
效果图:
MainActivity
public class MainActivity extends AppCompatActivity { private TabLayout tabLayout; private ViewPager2 viewPager2; private int activeColor = Color.parseColor("#ff678f"); private int normalColor = Color.parseColor("#666666"); private int activeSize = 20; private int normalSize = 14; private ArrayList fragments; private TabLayoutMediator mediator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tabLayout = findViewById(R.id.tab_layout); viewPager2 = findViewById(R.id.view_pager); final String[] tabs = new String[]{"关注", "推荐", "最新0", "最新1", "最新2", "最新3", "最新4", "最新5", "最新6"}; //禁用预加载 viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT); //Adapter viewPager2.setAdapter(new FragmentStateAdapter(getSupportFragmentManager(), getLifecycle()) { @NonNull @Override public Fragment createFragment(int position) { //FragmentStateAdapter内部自己会管理已实例化的fragment对象。 // 所以不需要考虑复用的问题 return TestFragment.newInstance(tabs[position]); } @Override public int getItemCount() { return tabs.length; } }); //viewPager 页面切换监听监听 viewPager2.registerOnPageChangeCallback(changeCallback); mediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() { @Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) { //这里可以自定义TabView TextView tabView = new TextView(MainActivity.this); int[][] states = new int[2][]; states[0] = new int[]{android.R.attr.state_selected}; states[1] = new int[]{}; int[] colors = new int[]{activeColor, normalColor}; ColorStateList colorStateList = new ColorStateList(states, colors); tabView.setText(tabs[position]); tabView.setTextSize(normalSize); tabView.setTextColor(colorStateList); tab.setCustomView(tabView); } }); //要执行这一句才是真正将两者绑定起来 mediator.attach(); } private ViewPager2.OnPageChangeCallback changeCallback = new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { //可以来设置选中时tab的大小 int tabCount = tabLayout.getTabCount(); for (int i = 0; i < tabCount; i++) { TabLayout.Tab tab = tabLayout.getTabAt(i); TextView tabView = (TextView) tab.getCustomView(); if (tab.getPosition() == position) { tabView.setTextSize(activeSize); tabView.setTypeface(Typeface.DEFAULT_BOLD); } else { tabView.setTextSize(normalSize); tabView.setTypeface(Typeface.DEFAULT); } } } }; @Override protected void onDestroy() { mediator.detach(); viewPager2.unregisterOnPageChangeCallback(changeCallback); super.onDestroy(); }}
activity_main关键代码
- tabIndicatorColor 指示器颜色
- tabIndicatorHeight 指示器高度
- tabIndicatorFullWidth 设置为false 则指示器跟文本宽度一致
- tabUnboundedRipple 设置为true点击时会有一个水波纹效果
- tabGravity 可设置center或fill;center指的是居中显示,fill指的是沾满全屏。
- tabMode 可设置fixed和 scrollable;fixed:指的是固定tab;scrollable指的是tab可滑动。
- tabTextColor tab文字颜色
- tabSelectedTextColor 选中时的tab颜色
viewPager2可以通过设置android:orientation属性来设置切换方向,支持上下、左右切换。
TestFragment
对应tab页面的实现效果在Fragment中进行实现。
public class TestFragment extends Fragment { private View rootView; public static TestFragment newInstance(String text) { Bundle args = new Bundle(); args.putString("text", text); TestFragment fragment = new TestFragment(); fragment.setArguments(args); return fragment; } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_test, container, false); return rootView; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); TextView textView = rootView.findViewById(R.id.text_view); String text = getArguments() != null ? getArguments().getString("text") : null; textView.setText(text); }}
几个注意的点!!
- ViewPager2获取当前fragment,通过mFragmentManager.findFragmentByTag(XXX); tag前面需要拼接“f”
看下源码tag怎么设置的,调用链如下:
FragmentStateAdapter-》onBindViewHolder-》placeFragmentInViewHolder方法
mFragmentManager.beginTransaction() .add(fragment, "f" + holder.getItemId()) .setMaxLifecycle(fragment, STARTED) .commitNow();
- ViewPager.
setOffscreenPageLimit
()设置预加载与缓存
(1)ViewPager 会预加载几页
(2)ViewPager 会缓存 2*n+1 页(n为设置的值)
如设置为n=1,预加载页数1页,缓存页数3页。如果当前在第一页,会预加载第二页,滑倒第二页,会预加载第三页,当滑倒第三页,第一页会销毁,第四页会加载。
来源地址:https://blog.csdn.net/u013773608/article/details/127997374