写在前面
目前大多数的APP都采用的是几个Tab标签以及多个界面滑动的形式来提供多层次的交互体验,最为常用的做法就是采用TabLayout+ViewPager+Fragment的方式,最近在公司项目中遇到类似的界面,也看了各个论坛很多份博客,但是发现都没有完全把这种方法的坑填完,因此写下这篇博客,一方面是对知识的总结,另一方面也能让其他开发者们少走一些弯路,博客内容主要分为四个章节:
- TabLayout+ViewPager+Fragment的简单用法总结。
- 所使用的两种PagerAdapter的差别分析及选择。
- 懒加载策略。
- 卡顿及性能优化建议。
一般情况下上面四个章节的内容足以应付过来,但是往往在一些特殊的情况下,仍然会遇到一些不能解决的问题,这时就需要深入到源码之中来具体问题具体分析。话不多说,接下来将进行使用总结。
TabLayout+ViewPager+Fragment的用法
首先,需要引入工具包:
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
用法其实非常简单,有点类似于RecyclerView,其中主要关心四个对象:Tablayout、ViewPager、PagerAdapter、Fragment。前两个就跟普通的View控件一样,可以直接通过XML来进行布局以及在onCreate获取相应的实例:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.TabLayoutActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tl_tabs"
android:layout_width="match_parent"
android:layout_height="40dp" />
<android.support.v4.view.ViewPager
android:id="@+id/vp_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Fragment建议采用v4兼容包下的,我们所需要使用的Fragment是需要自己来实现,但是和普通的Fragment没什么区别,因此也就省略了Fragment的创建步骤,而PagerAdapter有两种实现可以使用,具体会在下一小节介绍,TabLayout+ViewPager+Fragment方法的使用流程:
- 创建存储多个Fragment实例的列表
- 创建PagerAdapter实例并关联到Viewpager中
- 将ViewPager关联到Tablayout中
- 根据需求改写Tablayout属性*
最后一步不是必须的,为了更加清楚地描述这个调用流程,贴上一个示意图:
贴上代码:
public class TabLayoutActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {
TabLayout tabLayout;
ViewPager viewPager;
List<Fragment> fragments = new ArrayList<>();
List<String> titles = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_layout);
tabLayout = findViewById(R.id.tl_tabs);
viewPager = findViewById(R.id.vp_content);
fragments.add(MyFragment.newInstance("11111", "11111"));
fragments