6.TabLayout✅

TabLayout 是 Android 中用于创建标签式导航的组件,通常和 ViewPager 一起使用来实现可滑动的视图切换。它提供了一个简单的 UI 控件,允许用户通过点击标签或滑动来切换视图。

在 Kotlin 中,TabLayout 的使用方式通常如下:

1. 添加依赖

在 build.gradle 文件中添加 TabLayout 和 ViewPager2 的依赖(ViewPager2 是新版的 ViewPager,推荐使用):

dependencies {
    implementation "com.google.android.material:material:1.5.0"
    implementation "androidx.viewpager2:viewpager2:1.0.0"
}

1.1 常用属性

  <com.google.android.material.tabs.TabLayout
            android:id="@+id/tlyTab"
            android:layout_width="0dp"
            android:layout_height="35dp"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:textAlignment="center"
            app:tabBackground="@android:color/transparent"
            app:tabIndicator="@color/common_transparent"
            app:tabIndicatorColor="@color/common_transparent"
            app:tabIndicatorFullWidth="false"
            app:tabIndicatorHeight="8dp"
            app:tabMinWidth="0dp"
            app:tabMode="scrollable"
            app:tabPaddingBottom="0dp"
            app:tabPaddingEnd="6dp"
            app:tabPaddingStart="6dp"
            app:tabPaddingTop="0dp"
            app:tabRippleColor="@null"
            app:tabSelectedTextColor="#000000"
            app:tabTextAppearance="@style/TabTextLayoutTopTab"
            app:tabTextColor="#8E8A99" />  

这段代码是 TabLayout 的布局定义,其中有许多自定义属性。下面是各个属性的解释:

@1. android:layout_width="0dp"
• 作用:定义 TabLayout 的宽度。设置为 0dp 是为了和父容器的 layout_weight 配合使用,通过 layout_weight 来分配宽度。

@2. android:layout_height="35dp"
• 作用:定义 TabLayout 的高度为 35dp。

@3. android:layout_weight="1"
• 作用:当 TabLayout 位于 LinearLayout 中时,layout_weight 可以控制该组件所占用的剩余空间的比例。1 表示它会占据剩余空间的 1 倍。

@4. android:background="@android:color/transparent"
• 作用:设置 TabLayout 的背景为透明色。

@5. android:textAlignment="center"
• 作用:设置 TabLayout 中的文本对齐方式为居中。

@6. app:tabBackground="@android:color/transparent"
• 作用:设置每个 tab 项的背景为透明。此属性可用于自定义 tab 的背景。

@7. app:tabIndicator="@color/common_transparent"
• 作用:设置 tab 指示器(通常是下划线)的背景颜色。在此处设置为透明,意味着 tab 下方没有可见的指示器。

@8. app:tabIndicatorColor="@color/common_transparent"
• 作用:设置 tab 指示器的颜色。在此例中,设置为透明色,指示器将不可见。

@9. app:tabIndicatorFullWidth="false"
• 作用:如果设置为 true,指示器会扩展到整个 tab 的宽度;如果设置为 false,指示器的宽度将仅与文本宽度匹配。

@10. app:tabIndicatorHeight="8dp"
• 作用:设置指示器的高度为 8dp。通常情况下,这个指示器是 tab 下方的横线,用于标识当前选中的 tab。

@11. app:tabMinWidth="0dp"
• 作用:设置 tab 最小宽度。0dp 表示 tab 宽度不会有最小限制,它将根据内容大小来调整宽度。

@12. app:tabMode="scrollable"
• 作用:设置 TabLayout 的模式为 scrollable,意味着当 tab 项过多时,tab 会变得可滑动。如果不设置为 scrollable,tab 会在一行显示不下时缩小尺寸。

@13. app:tabPaddingBottom="0dp"
• 作用:设置 tab 项底部的内边距为 0dp,也就是没有额外的空间。

@14. app:tabPaddingEnd="6dp"
• 作用:设置 tab 项右侧的内边距为 6dp。

@15. app:tabPaddingStart="6dp"
• 作用:设置 tab 项左侧的内边距为 6dp。

@16. app:tabPaddingTop="0dp"
• 作用:设置 tab 项顶部的内边距为 0dp。

@17. app:tabRippleColor="@null"
• 作用:设置 tab 的点击波纹效果。@null 表示禁用点击时的波纹效果。

@18. app:tabSelectedTextColor="#000000"
• 作用:设置选中 tab 时,文本的颜色为黑色 (#000000)。

@19. app:tabTextAppearance="@style/TabTextLayoutTopTab"
• 作用:应用自定义的文本样式,TabTextLayoutTopTab 是你自定义的样式,里面包含了 tab 文本的字体大小、颜色等属性。

@20. app:tabTextColor="#8E8A99"
• 作用:设置未选中时,tab 文本的颜色为 #8E8A99(一种灰色调)。

2. 布局文件

你需要在布局文件中添加 TabLayout 和 ViewPager2。

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- TabLayout -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@android:color/holo_blue_light"
        app:tabSelectedTextColor="@android:color/holo_blue_light"
        app:tabTextColor="@android:color/darker_gray"/>

    <!-- ViewPager2 -->
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/tabLayout"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

3. 设置适配器和连接 TabLayout 和 ViewPager2

在你的 Activity 或 Fragment 中,设置 ViewPager2 的适配器,并将它和 TabLayout 进行绑定。

class MainActivity : AppCompatActivity() {

    private lateinit var tabLayout: TabLayout
    private lateinit var viewPager: ViewPager2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tabLayout = findViewById(R.id.tabLayout)
        viewPager = findViewById(R.id.viewPager)

        val adapter = ViewPagerAdapter(this)
        viewPager.adapter = adapter

        // Connect the TabLayout with ViewPager
        TabLayoutMediator(mBinding.tlyTab, viewPager2) { tab, position ->
            tab.customView = AppCompatTextView(mContext).apply {
                text = list[position]
                textSize = 15f
                maxLines = 1
                typeface = resources.getFont(com.smile.common.R.font.sans_pro_black)
                if (skinConfigBean.isOpen) {
                    setTextColor(Color.parseColor(skinConfigBean.titleColor))
                } else {
                    setTextColor(Color.parseColor("#8E8A99"))
                }
            }
        }.attach()
    }
}

4. 创建适配器

ViewPagerAdapter 是一个继承自 FragmentStateAdapter 的适配器,用来管理每个 tab 页面显示的内容。

class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {

    override fun getItemCount(): Int {
        return 3 // Number of tabs
    }

    override fun createFragment(position: Int): Fragment {
        return when (position) {
            0 -> Fragment1()
            1 -> Fragment2()
            2 -> Fragment3()
            else -> Fragment1()
        }
    }
}

5. 创建各个 Fragment

你可以为每个 tab 页面创建对应的 Fragment,比如:

class Fragment1 : Fragment(R.layout.fragment_1) {
    // Your code for fragment 1
}

class Fragment2 : Fragment(R.layout.fragment_2) {
    // Your code for fragment 2
}

class Fragment3 : Fragment(R.layout.fragment_3) {
    // Your code for fragment 3
}

6.动态设置tab的文字大小和颜色

  val tabCount = mBinding.tlyTab.tabCount
        for (i in 0 until tabCount) {
            val tab = mBinding.tlyTab.getTabAt(i)
            if (tab != null) {
                // 根据 tab 的位置来判断是否选中
                val isSelected = i == mBinding.vpPager.currentItem
                updateTabSelect(skinConfigBean, i, isSelected)
            }
        }
    //设置tablayout底部图标
        initTabBottomDrawable(skinConfigBean)

 /**
     * description:初始化tablayout底部图标(底部图标如果是从网路下载,会被拉伸,用这个方式进行实现)
     */
    private fun initTabBottomDrawable(skinConfigBean: SkinConfigBean) {
        // 设置tablayout底部图标初始位置
        mBinding.tlyTab.postDelayed({
            // 获取当前选中的tab
            val selectedTab: TabLayout.Tab? = mBinding.tlyTab.getTabAt(1)
            if (selectedTab?.customView != null) {
                // 获取tab的宽度和位置
                val tabWidth = selectedTab.customView!!.width.toFloat()
                val location = IntArray(2)
                selectedTab.getCustomView()!!.getLocationOnScreen(location)
                val targetXFixed = location[0]
                // 设置黄色按钮初始位置(在tab底部正中间)
                val initialX: Float = targetXFixed + (tabWidth - mBinding.ivFragmentTab.getWidth()) / 2
                mBinding.ivFragmentTab.setX(initialX)
                mBinding.ivFragmentTab.setY(location[1].toFloat() + UiUtil.dp2Px(22 - 4, mContext))
            }
        }, 50)
        //设置tablayout底部图标
        if (skinConfigBean.isOpen) {
            skinConfigBean.titleBottom?.let {
                SkinManager.setViewBackgroundDrawable(mContext, mBinding.ivFragmentTab, skinConfigBean.titleBottom)
            } ?: run {
                mBinding.ivFragmentTab.setBackgroundResource(R.drawable.iv_indicator_tab_square_new)
            }
        } else {
            mBinding.ivFragmentTab.setBackgroundResource(R.drawable.iv_indicator_tab_square_new)
        }
    }
//在tab切换的时候,动态设置bottomDrawable的位置
override fun onSelect(position: Int) {
                        updateTabSelect(mSkinConfigBeanDefault, position, true)
                        mBinding.tlyTab.postDelayed({  // 获取选中tab的位置
                            val selectedTab: TabLayout.Tab? = mBinding.tlyTab.getTabAt(position)
                            if (selectedTab?.customView != null) {
                                val location = IntArray(2)
                                selectedTab.getCustomView()!!.getLocationOnScreen(location)
                                val targetXFixed = location[0]
                                // 获取tab的宽度
                                val tabWidth: Float = selectedTab.getCustomView()!!.getWidth().toFloat()
                                // 计算按钮中心点位置,确保黄色按钮在选中tab的底部正中间
                                val targetCenterX: Float = targetXFixed + (tabWidth - mBinding.ivFragmentTab.getWidth()) / 2
                                // 创建平移动画
                                val animator = ObjectAnimator.ofFloat(mBinding.ivFragmentTab, "translationX", mBinding.ivFragmentTab.getX(), targetCenterX)
                                animator.setDuration(300) // 设置动画时间
                                animator.start()
                            }
                        }, 50)
                    }

这样就完成了一个基本的 TabLayout 和 ViewPager2 的集成,允许用户通过点击 Tab 或滑动来切换不同的内容页面。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 8,570评论 0 5
  • 为了让我有一个更快速、更精彩、更辉煌的成长,我将开始这段刻骨铭心的自我蜕变之旅!从今天开始,我将每天坚持阅...
    李薇帆阅读 6,020评论 0 3
  • 似乎最近一直都在路上,每次出来走的时候感受都会很不一样。 1、感恩一直遇到好心人,很幸运。在路上总是...
    时间里的花Lily阅读 5,241评论 0 2
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 3,584评论 0 1
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 3,567评论 0 0