ViewPager+Fragment的组合是开发中比较常见的,而且这也是Google官方推荐的组合,因为Fragment有着完备的生命周期,所以能适合大多数需要使用ViewPager的场景。
ViewPager+Fragment的使用场景
最常见的,比如用户量最大的今日头条、网易新闻等,其主页面就是很明显的ViewPager跟众多的Fragment搭配,顶部再来一个风格各异的指示器。用户可以很随意的进行左右滑动的操作。总体来说,需要大量页面并列滑动的时候,ViewPager+Fragment就是非常好的选择。
ViewPager+Fragment的代码实现
先来一个最简单的Fragment的代码,布局就不展示了,里面只有一个居中的TextView,Java代码也十分简单,就是把TextView的内容设置为其在ViewPager中的位置:
public class VPFragment extends Fragment { private TextView mTextView; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_viewpager, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { mTextView = view.findViewById(R.id.mTextView); mTextView.setText("这是第" + getArguments().getInt("position") + "个Fragment"); } }
我们知道,ViewPager是需要绑定一个PagerAdapter的,当然你依然可以自己手写,但是实际上Google已经给我们提供好了:FragmentPagerAdapter和FragmentStatePagerAdapter这2个PagerAdapter的实现,我们只需要从中选择一个使用即可。在Fragment数量不是特别大的时候,使用FragmentPagerAdapter足矣。由于FragmentPagerAdapter内部已经实现好了instantiateItem和destroyItem方法,所以我们只需要实现一个传入FragmentManager参数的构造方法和getItem、getCount这2个方法即可:
public class TestFragmentAdapter extends FragmentPagerAdapter { public TestFragmentAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Fragment fragment = new VPFragment(); Bundle bundle = new Bundle(); bundle.putInt("position", i); fragment.setArguments(bundle); return fragment; } @Override public int getCount() { return 5; } }
然后把ViewPager与Adapter进行绑定:
vpTest.setAdapter(new TestFragmentAdapter(getSupportFragmentManager()));
效果嘛,因为我这里给出的Fragment实在是太过简陋,所以大家看到滑动的效果就可以了:
当然了这只是最简单的运用了。实际上你可以把Fragment写得更复杂一些,而且数量上也没有什么限制,设置成int的最大值都可以,只要你能处理好每个位置的Fragment实现就行。
ViewPager+Fragment+TabLayout的组合使用
TabLayout是Google在Support:Design包里为我们提供的一个指示器,它继承自HorizontalScrollView,所以实际上它是一个可以横向滑动的控件。很多时候,我们都会用它来跟ViewPager搭配,而ViewPager+Fragment+TabLayout也是开发中十分经典常用的组合,大部分情况下能够满足相应的产品需求。
想要给ViewPager配一个相应的TabLayout,需要的代码很少,因为Google其实内部给TabLayout做了很多的工作,开发者使用起来是非常方便的。记住,别忘了在build.gradle中添加com.android.support:design的依赖。
先在布局文件里声明一下,一般情况下都是直接放在ViewPager上方的:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="40dp" app:layout_constraintTop_toTopOf="parent"/> <android.support.v4.view.ViewPager android:id="@+id/vpTest" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@+id/tabLayout" app:layout_constraintBottom_toBottomOf="parent"/> </android.support.constraint.ConstraintLayout>
然后把TabLayout与ViewPager进行绑定:
tabLayout.setupWithViewPager(vpTest);
接下来需要把PagerAdapter在之前实现的基础上,再额外覆盖一个getPageTitle方法,这个方法就决定了TabLayout在相应位置应该怎么显示标题:
public class TestFragmentAdapter extends FragmentPagerAdapter { public TestFragmentAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Fragment fragment = new VPFragment(); Bundle bundle = new Bundle(); bundle.putInt("position", i); fragment.setArguments(bundle); return fragment; } @Override public int getCount() { return 5; } @Nullable @Override public CharSequence getPageTitle(int position) { return "标题" + position; } }
再来看一下运行效果:
当然了,TabLayout实际上还能有别的一些设置,不过Google为我们提供的原生TabLayout能做的调整不多,只能满足大多数时候的一般需求。如果对指示器的产品需求比较复杂,可能就需要我们自定义实现或者使用一些开源库了。
总结
ViewPager+Fragment+TabLayout的组合简单好用,而且如果再配合CoordinatorLayout更是能实现非常好的体验。当然了,很多人现在都喜欢用RecyclerView去实现ViewPager的效果了,原因是RecyclerView更新、更强大,而且目前Google新推的AndroidX(一个新库,可以大致理解为Support库的升级版)里的ViewPager2,内部也是由RecyclerView实现的,喜欢尝鲜的朋友可以去了解、使用。
需要注意的是,这里需要使用的Fragment是android.support.v4.app下的Fragment,而不是android.app下的Fragment。原因嘛,直接去看FragmentPagerAdapter或FragmentStatePagerAdapter就知道了,里面的Fragment就是android.support.v4.app.Fragment。另外,目前android.app.Fragment已经被加上了@Deprecated注解了,它已经过时了,Google已经不推荐使用了,原因是v4下的Fragment现在支持Lifecycle了,更好用,而且总维持2个Fragment类也会让开发者混淆吧。
评论