记一次ViewPager2+TabLayout+ Fragment简单使用

4,349 阅读2分钟

这是我参与新手入门的第3篇文章

背景

由于项目要求, 需要实现一个Tab+ViewPager2联动滚动的功能, 下面是记一次简单使用

导包

implementation 'com.google.android.material:material:1.3.0'

XML代码

<?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"
    android:background="@color/white"
    tools:context=".ui.group.GroupMemberListFragment">

    <RelativeLayout
        android:id="@+id/rl_action_bar"
        android:layout_width="match_parent"
        android:layout_height="88dp"
        android:background="@drawable/bg_action_bar">

        <ImageView
            android:id="@+id/iv_action_bar_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="start|bottom"
            android:layout_marginStart="18dp"
            android:layout_marginTop="?actionBarSize"
            android:scaleType="centerInside"
            android:src="@drawable/ic_arrow_left" />

        <TextView
            android:id="@+id/tv_group_search"
            android:layout_width="match_parent"
            android:layout_height="36dp"
            android:layout_gravity="start|bottom"
            android:layout_marginStart="17dp"
            android:layout_marginTop="?actionBarSize"
            android:layout_marginEnd="25dp"
            android:layout_marginBottom="4dp"
            android:layout_toEndOf="@id/iv_action_bar_left"
            android:background="@drawable/bg_group_search"
            android:drawablePadding="8dp"
            android:paddingStart="8dp"
            android:gravity="center_vertical"
            android:hint="@string/group_search_members"
            android:textColorHint="@color/app_text_hint_color"
            android:textSize="@dimen/app_text_size_14"
            app:drawableStartCompat="@drawable/ic_group_search"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@id/iv_action_bar_left" />
    </RelativeLayout>
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        app:tabMode="scrollable"
        android:layout_gravity="center_horizontal"
        app:tabSelectedTextColor="@color/app_theme_color"
        app:tabIndicatorColor="@color/app_theme_color"
        app:tabTextAppearance="@style/TabLayoutTextStyle"
        android:background="@color/white"
        app:tabTextColor="@color/black"
        app:tabIndicatorFullWidth="false"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        app:tabMaxWidth="0dp"
        app:tabGravity="fill"
        app:tabRippleColor="@color/trans" />
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

初始化代码,使TabLayout和ViewPager2管理

private fun initData() {
        val fragments = arrayListOf<GroupMemberListContentFragment>()
        val tabTitles = arrayListOf<String>()
        val participantList = activity?.resources?.getStringArray(R.array.group_member_list_arrays)
        if (participantList != null) {
            for (data in participantList) {
                tab_layout.addTab(tab_layout.newTab())
                tabTitles.add(data)
                when(data){
                    resources.getString(R.string.group_member_list_all) ->{
                        fragments.add(GroupMemberListContentFragment.getInstance(RESULT_ALL))
                    }
                    resources.getString(R.string.positive) ->{
                        fragments.add(GroupMemberListContentFragment.getInstance(RESULT_FAIL))
                    }
                    resources.getString(R.string.negative) ->{
                        fragments.add(GroupMemberListContentFragment.getInstance(RESULT_PASS))
                    }
                    resources.getString(R.string.group_no_result) ->{
                        fragments.add(GroupMemberListContentFragment.getInstance(RESULT_INVALID))
                    }
                    else ->{
                        fragments.add(GroupMemberListContentFragment.getInstance(RESULT_ALL))
                    }
                }

            }
            viewpager.apply {
                adapter = ViewPagerFmAdapter(childFragmentManager, lifecycle, fragments)
                // 优化体验设置该属性后第一次将自动加载所有fragment 在子fragment内部添加懒加载机制
                offscreenPageLimit = fragments.size
                //指定滚动到第几页,默认为0
                currentItem = mViewModel.currentItem
            }
            viewpager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback(){
                override fun onPageSelected(position: Int) {
                    super.onPageSelected(position)
                    //记录当前滚动到的页数
                    mViewModel.currentItem = position
                }
            })
            //使用.attach()将TabLayout和ViewPager2进行绑定,如果没有这步操作将不会联动
            TabLayoutMediator(tab_layout, viewpager) { tab, position ->
                //根据position修改tab的样式和文字等
                tab.text = tabTitles[position]
            }.attach()

        }
    }

PS:material1.1.0之前,material包是不包含TabLayoutMediator的,如果发现jar包中没有相关类,需检查material版本

在Fragment中进行懒加载

override fun onResume() {
        super.onResume()
        // 懒加载 仅加载指定的fragment的数据缓存
        if (firstLoad && parentFragment is GroupMemberListFragment && (parentFragment as GroupMemberListFragment).viewpager.currentItem == mViewModel.currentItem) {
            //刷新数据或者加载数据操作
            group_user_refresh.autoRefresh()
        }
    }

常用的几个方法

viewpager.currentItem指定需要初始化第几页
viewpager.adapter设置ViewPager2的适配器
viewpager.offscreenPageLimit设置第一次需要加载的页面数量
viewpager.registerOnPageChangeCallback注册监听页面改变回调
viewpager.unregisterOnPageChangeCallback销毁监听
TabLayoutMediator.attach关联TabLayout和ViewPager2联动
TabLayoutMediator.detach销毁TabLayout和ViewPager2关联

常用的几个属性

  • TabLayout
    app:tabMode可选属性有两个scrollable滚动fixed为固定不可滚动,在多个tab时可能会被挤压
    app:tabSelectedTextColor选中文字颜色
    app:tabSelectedTextColor标签指示器颜色
    app:tabTextAppearance设置TabLayout内部字体大小
    app:tabTextColortab文字颜色(未被选中颜色)
    app:tabIndicatorFullWidthIndicator是否充满item
    app:tabMaxWidthtab最大宽度
    app:tabGravitytab中文件显示位置,目前找到三种start, center以及 fill
    app:tabRippleColor点击tab时波纹颜色