Android TabLayout实现ViewPager嵌套和自定义指示器图片

先上图片

上代码

一、BaseText去设置TabLayout文字样式

import android.content.Context
import android.view.Gravity
import android.widget.TextView
import com.google.android.material.tabs.TabLayout

open class BaseText {

    protected var context: Context? = null
    protected var tabLayout: TabLayout? = null
    protected var normalTextBold: Boolean = false
    protected var selectTextBold: Boolean = false
    protected var normalTextSize: Float = 14f
    protected var selectTextSize: Float = 14f

    fun bindTabLayout(tabLayout: TabLayout) {
        this.tabLayout = tabLayout
        this.context = tabLayout.context
    }

    fun setNormalTextBold(normalTextBold: Boolean): BaseText {
        this.normalTextBold = normalTextBold
        return this
    }

    fun setSelectTextBold(selectTextBold: Boolean): BaseText {
        this.selectTextBold = selectTextBold
        return this
    }

    fun setNormalTextSize(normalTextSize: Float): BaseText {
        this.normalTextSize = normalTextSize
        return this
    }

    fun setSelectTextSize(selectTextSize: Float): BaseText {
        this.selectTextSize = selectTextSize
        return this
    }

    fun bind() {
        tabLayout?.post {
            tabLayout?.apply {
                for (i in 0 until tabCount) {
                    getTabAt(i)?.let {
                        it.customView = TextView(context).apply {
                            text = it.text
                            textSize =
                                if (selectedTabPosition == i) selectTextSize else normalTextSize
                            if (selectedTabPosition == i)
                                paint?.isFakeBoldText = selectTextBold
                            else
                                paint?.isFakeBoldText = normalTextBold
                            gravity = Gravity.CENTER
                            setTextColor(tabTextColors)
                        }
                    }
                }

                addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
                    override fun onTabReselected(tab: TabLayout.Tab?) {
                        (tab?.customView as? TextView)?.apply {
                            textSize = selectTextSize
                            paint?.isFakeBoldText = selectTextBold
                        }
                    }

                    override fun onTabUnselected(tab: TabLayout.Tab?) {
                        (tab?.customView as? TextView)?.apply {
                            textSize = normalTextSize
                            paint?.isFakeBoldText = normalTextBold
                        }
                    }

                    override fun onTabSelected(tab: TabLayout.Tab?) {
                        (tab?.customView as? TextView)?.apply {
                            textSize = selectTextSize
                            paint?.isFakeBoldText = selectTextBold
                        }
                    }

                })
            }
        }

    }
}

二、设置指示器样式

1.BaseIndicator.kt 基类
import android.content.Context
import androidx.annotation.ColorInt
import androidx.annotation.Px
import com.google.android.material.tabs.TabLayout

abstract class BaseIndicator {
    companion object {
        //填充满
        const val MATCH = -1
    }

    protected var width: Int = 0
    protected var height: Int = 0
    protected var context: Context? = null
    protected var tabLayout: TabLayout? = null

    fun bindTabLayout(tabLayout: TabLayout) {
        this.tabLayout = tabLayout
        this.context = tabLayout.context


    }

    fun setColor(@ColorInt color: Int): BaseIndicator {
        tabLayout?.setSelectedTabIndicatorColor(color)
        return this
    }

    fun setWidth(@Px width: Int): BaseIndicator {
        this.width = width
        return this
    }

    fun setHeight(@Px height: Int): BaseIndicator {
        this.height = height
        return this
    }
    
    fun setGravity(gravity: Int): BaseIndicator {
        tabLayout?.setSelectedTabIndicatorGravity(gravity)
        return this
    }

    abstract fun bind()
}
2.LinearIndicator.kt 线性指示器样式
import android.graphics.Paint
import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.RoundRectShape
import android.os.Build
import android.view.Gravity
import com.google.android.material.tabs.TabLayout
import com.loper7.tab_expand.ext.toPx

open class LinearIndicator : BaseIndicator() {

    private var angle: Int = 0


    fun setAngle(angle: Int): LinearIndicator {
        this.angle = angle
        return this
    }

    override fun bind() {
        tabLayout?.post {
            val drawable = ShapeDrawable()
            if (height == MATCH)
                height = tabLayout?.height!!
            if (angle <= 0f)
                angle = if (height == 0) 100 else height / 2
            val f_angle = angle.toFloat()
            val outerR =
                floatArrayOf(f_angle, f_angle, f_angle, f_angle, f_angle, f_angle, f_angle, f_angle)
            val shape = RoundRectShape(outerR, null, null)
            drawable.shape = shape
            drawable.paint.style = Paint.Style.FILL

            val layerDrawable = LayerDrawable(arrayOf(drawable))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                layerDrawable.setLayerHeight(0, height)
                layerDrawable.setLayerWidth(0, width)
                layerDrawable.setLayerGravity(0, Gravity.CENTER)
            }


            if (width == 0 && height == 0)
                tabLayout?.setSelectedTabIndicator(drawable)
            else
                tabLayout?.setSelectedTabIndicator(layerDrawable)

            if (height == 0)
                tabLayout?.setSelectedTabIndicatorHeight(3.toPx())
            else
                tabLayout?.setSelectedTabIndicatorHeight(height)

            //对自适应宽度进行处理
            if (width <= 0 && tabLayout?.tabSelectedIndicator is LayerDrawable) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    (tabLayout?.tabSelectedIndicator as LayerDrawable).setLayerWidth(
                        0,
                        tabLayout?.getTabAt(0)!!.view.width
                    )
                }
                tabLayout?.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
                    override fun onTabReselected(tab: TabLayout.Tab?) {
                    }

                    override fun onTabUnselected(tab: TabLayout.Tab?) {
                    }

                    override fun onTabSelected(tab: TabLayout.Tab?) {
                        tab?.apply {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                (tabLayout?.tabSelectedIndicator as LayerDrawable).setLayerWidth(
                                    0,
                                    tab.view.width
                                )
                            }
                        }
                    }

                })
            }
        }
    }
}
3.TriangleIndicator.kt 三角指示器样式
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.view.Gravity
import androidx.core.content.ContextCompat
import com.loper7.tab_expand.R
import com.loper7.tab_expand.ext.toPx

open class TriangleIndicator : BaseIndicator() {

    private var path = Path.POSITIVE
    private var drawable: Drawable? = null

    fun setPath(path: Path): TriangleIndicator {
        this.path = path
        return this
    }


    override fun bind() {
        tabLayout?.post {
            if (height == MATCH)
                height = tabLayout?.height!!

            if (drawable == null) {
                drawable = if (path == Path.POSITIVE) {
                    ContextCompat.getDrawable(context!!, R.drawable.tab_indicator_triangle_z)!!
                } else {
                    ContextCompat.getDrawable(context!!, R.drawable.tab_indicator_triangle_f)!!
                }
            }

            if (width == 0)
                width = 12.toPx()
            if (height == 0)
                height = 12.toPx()

            if (height == 0)
                tabLayout?.setSelectedTabIndicatorHeight(3.toPx())
            else
                tabLayout?.setSelectedTabIndicatorHeight(height)

            val layerDrawable = LayerDrawable(arrayOf(drawable))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                layerDrawable.setLayerHeight(0, height)
                layerDrawable.setLayerWidth(0, width)
                layerDrawable.setLayerGravity(0, Gravity.CENTER)
            }


            tabLayout?.setSelectedTabIndicator(layerDrawable)
        }

    }

    enum class Path {
        /**
         * POSITIVE 正
         * NEGATIVE 反
         */
        POSITIVE,
        NEGATIVE
    }
}
4.CustomIndicator.kt 自定义图片指示器样式
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.view.Gravity
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.google.android.material.tabs.TabLayout
import com.loper7.tab_expand.ext.toPx


open class CustomIndicator : BaseIndicator() {

    private var drawable: Drawable? = null

    fun setDrawable(drawable: Drawable): CustomIndicator {
        this.drawable = drawable
        return this
    }

    fun setDrawable(@DrawableRes resId: Int): CustomIndicator {
        this.drawable = ContextCompat.getDrawable(context!!, resId)
        return this
    }

    override fun bind() {
        tabLayout?.post {

            if (height == MATCH)
                height = tabLayout?.height!!

            val layerDrawable = LayerDrawable(arrayOf(drawable))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                layerDrawable.setLayerHeight(0, height)
                layerDrawable.setLayerWidth(0, width)
                layerDrawable.setLayerGravity(0, Gravity.CENTER)
            }

            if (width == 0 && height == 0)
                tabLayout?.setSelectedTabIndicator(drawable)
            else
                tabLayout?.setSelectedTabIndicator(layerDrawable)


            if (height == 0)
                tabLayout?.setSelectedTabIndicatorHeight(3.toPx())
            else
                tabLayout?.setSelectedTabIndicatorHeight(height)

            //对自适应宽度进行处理
            if (width <= 0 && tabLayout?.tabSelectedIndicator is LayerDrawable) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    (tabLayout?.tabSelectedIndicator as LayerDrawable).setLayerWidth(
                        0,
                        tabLayout?.getTabAt(0)!!.view.width
                    )
                }
                tabLayout?.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
                    override fun onTabReselected(tab: TabLayout.Tab?) {
                    }

                    override fun onTabUnselected(tab: TabLayout.Tab?) {
                    }

                    override fun onTabSelected(tab: TabLayout.Tab?) {
                        tab?.apply {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                (tabLayout?.tabSelectedIndicator as LayerDrawable).setLayerWidth(
                                    0,
                                    tab.view.width
                                )
                            }
                        }
                    }

                })
            }
        }
    }
}

三、工具类和接口

fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
fun Double.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
fun Double.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
import com.google.android.material.tabs.TabLayout
import com.loper7.tab_expand.indicator.BaseIndicator
import com.loper7.tab_expand.text.BaseText

/**
 * 绑定tabLayout指示器
 */
inline fun <reified T : BaseIndicator> TabLayout.buildIndicator():T {
    val indicator = T::class.java.newInstance()
    indicator.bindTabLayout(this)
    return indicator
}

/**
 * 绑定tabLayout文字设置
 */
inline fun <reified T : BaseText> TabLayout.buildText():T {
    val text = T::class.java.newInstance()
    text.bindTabLayout(this)
    return text
}

四、使用方式

MainActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.content.ContextCompat
import com.google.android.material.tabs.TabLayout
import com.loper7.tablayout_ext.adapter.MainFragmentAdapter
import com.loper7.tablayout_ext.helper.StatusBarHelper
import com.loper7.tab_expand.ext.buildIndicator
import com.loper7.tab_expand.ext.buildText
import com.loper7.tab_expand.ext.toPx
import com.loper7.tab_expand.indicator.CustomIndicator
import com.loper7.tab_expand.indicator.LinearIndicator
import com.loper7.tab_expand.text.BaseText
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.tabLayout
import kotlinx.android.synthetic.main.activity_main.viewPager
import kotlinx.android.synthetic.main.fragment_other_indicator.*

class MainActivity : AppCompatActivity() {

    private lateinit var adapter:MainFragmentAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        StatusBarHelper.setDarkStatusIcon(this,true)


        adapter = MainFragmentAdapter(supportFragmentManager)
        viewPager.adapter = adapter
        viewPager.offscreenPageLimit = 3
        tabLayout.setupWithViewPager(viewPager)

        tabLayout.buildIndicator<CustomIndicator>()
            .setDrawable(ContextCompat.getDrawable(this, R.mipmap.icon_indicator)!!)
            .setWidth(15.toPx())
            .setHeight(6.toPx())
            .bind()
        tabLayout.buildText<BaseText>()
            .setNormalTextBold(true)
            .setSelectTextSize(15f)
            .setSelectTextBold(true).bind()
    }
}
activity_main.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:background="#FFFFFF"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dp"
        app:tabIndicatorColor="#FFBB33"
        app:tabIndicatorFullWidth="false"
        app:tabIndicatorHeight="4dp"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />

    <View
        android:layout_width="match_parent"
        android:layout_height="0.6dp"
        android:background="#EEEEEE" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
fragment
1.线性
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import com.loper7.tab_expand.ext.buildIndicator
import com.loper7.tab_expand.ext.buildText
import com.loper7.tab_expand.ext.toPx
import com.loper7.tab_expand.indicator.BaseIndicator
import com.loper7.tab_expand.indicator.LinearIndicator
import com.loper7.tab_expand.text.BaseText
import com.loper7.tablayout_ext.R
import com.loper7.tablayout_ext.adapter.SimpleFragmentAdapter
import kotlinx.android.synthetic.main.fragment_linear_indicator.*

class LinearIndicatorFragment : Fragment() {
    var mRootView: View? = null
    private lateinit var adapter: SimpleFragmentAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        if (mRootView == null) {
            mRootView = View.inflate(
                context,
                R.layout.fragment_linear_indicator, null
            )
        }
        return mRootView
    }

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = SimpleFragmentAdapter(childFragmentManager)
        viewPager.adapter = adapter
        tabLayout_default.setupWithViewPager(viewPager)
        tabLayout.setupWithViewPager(viewPager)
        tabLayout1.setupWithViewPager(viewPager)
        tabLayout2.setupWithViewPager(viewPager)
        tabLayout3.setupWithViewPager(viewPager)
        tabLayout4.setupWithViewPager(viewPager)

        // LinearIndicator
        tabLayout.buildIndicator<LinearIndicator>().bind()
        tabLayout.buildText<BaseText>()
            .setNormalTextBold(false)
            .setSelectTextBold(true)
            .setNormalTextSize(16f)
            .setSelectTextSize(18f)
            .bind()
        // LinearIndicator (w=35,h=3.5)
        tabLayout1.buildIndicator<LinearIndicator>()
            .setWidth(35.toPx())
            .setHeight(4.toPx())
            .bind()
        tabLayout1.buildText<BaseText>()
            .setNormalTextBold(false)
            .setSelectTextBold(true)
            .bind()
        // LinearIndicator (w=5,h=5)
        tabLayout2.buildIndicator<LinearIndicator>()
            .setWidth(5.toPx())
            .setHeight(5.toPx())
            .bind()
        tabLayout2.buildText<BaseText>()
            .setNormalTextBold(false)
            .setSelectTextBold(true)
            .bind()
        // LinearIndicator (w=auto,h=match,a=4)
        tabLayout3.buildIndicator<LinearIndicator>()
            .setAngle(4.toPx())
            .setHeight(BaseIndicator.MATCH)
            .setWidth(BaseIndicator.MATCH)
            .bind()
        tabLayout3.buildText<BaseText>()
            .setNormalTextBold(true)
            .setSelectTextBold(true)
            .bind()
        // LinearIndicator (w=auto,h=22,a=auto)
        tabLayout4.buildIndicator<LinearIndicator>()
            .setHeight(22.toPx())
            .bind()

        tabLayout4.buildText<BaseText>()
            .setNormalTextBold(true)
            .setSelectTextBold(true)
            .bind()

        tabLayout.getTabAt(1)?.orCreateBadge?.backgroundColor = Color.parseColor("#FF9900")
        tabLayout.getTabAt(1)?.orCreateBadge?.number = 6
    }
}
fragment_linear_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="Default"
        android:textSize="12sp"
        android:textColor="@color/colorDescription"/>

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout_default"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_gravity="center"
        android:background="#F6F6F6"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingBottom="5dp"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabIndicatorFullWidth="false"
        app:tabIndicatorHeight="3dp"
        app:tabMode="scrollable"
        app:tabRippleColor="@android:color/transparent"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="LinearIndicator"
        android:textColor="@color/colorDescription"
        android:textSize="12sp" />
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:background="#F6F6F6"
        app:tabIndicatorFullWidth="false"
        android:paddingLeft="10dp"
        android:paddingBottom="5dp"
        android:paddingRight="10dp"
        android:layout_height="45dp"
        app:tabIndicatorHeight="3.5dp"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="LinearIndicator (w=35,h=3.5)"
        android:textSize="12sp"
        android:textColor="@color/colorDescription"/>
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout1"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:paddingLeft="10dp"
        android:background="#F6F6F6"
        android:paddingRight="10dp"
        android:paddingBottom="5dp"
        android:layout_height="45dp"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="LinearIndicator (w=5,h=5)"
        android:textSize="12sp"
        android:textColor="@color/colorDescription"/>
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout2"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:background="#F6F6F6"
        android:paddingLeft="10dp"
        android:paddingBottom="5dp"
        android:paddingRight="10dp"
        android:layout_height="45dp"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:text="LinearIndicator (w=auto,h=match,a=4)"
        android:textSize="12sp"
        android:textColor="@color/colorDescription"/>
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout3"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:layout_height="30dp"
        android:layout_marginTop="5dp"
        app:tabIndicatorGravity="center"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:layout_marginBottom="5dp"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="#F6F6F6"
        app:tabTextColor="@color/colorSubtext" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="10dp"
        android:text="LinearIndicator (w=auto,h=22,a=auto)"
        android:textSize="12sp"
        android:textColor="@color/colorDescription"/>
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout4"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:layout_height="30dp"
        android:layout_marginTop="5dp"
        android:paddingLeft="10dp"
        app:tabIndicatorGravity="center"
        android:paddingRight="10dp"
        android:layout_marginBottom="5dp"
        app:tabIndicatorColor="#2058B87F"
        app:tabRippleColor="@android:color/transparent"
        app:tabMode="scrollable"
        app:tabSelectedTextColor="@color/colorAccent"
        app:tabTextColor="@color/colorSubtext" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
2.三角
package com.loper7.tablayout_ext.fragment

import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.google.android.material.tabs.TabLayout
import com.loper7.tab_expand.ext.buildIndicator
import com.loper7.tab_expand.ext.toPx
import com.loper7.tab_expand.indicator.TriangleIndicator
import com.loper7.tablayout_ext.R
import com.loper7.tablayout_ext.adapter.SimpleFragmentAdapter
import kotlinx.android.synthetic.main.fragment_triangle_indicator.*

class TriangleIndicatorFragment :Fragment() {
    var mRootView: View? = null
    private lateinit var adapter: SimpleFragmentAdapter

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        if (mRootView == null) {
            mRootView = View.inflate(context, R.layout.fragment_triangle_indicator, null)
        }
        return mRootView
    }

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = SimpleFragmentAdapter(childFragmentManager)
        viewPager.adapter = adapter
        tabLayout.setupWithViewPager(viewPager)
        tabLayout1.setupWithViewPager(viewPager)
        tabLayout2.setupWithViewPager(viewPager)


        // TriangleIndicator
        tabLayout.buildIndicator<TriangleIndicator>().bind()
        // TriangleIndicator(p=NEGATIVE)
        tabLayout1.buildIndicator<TriangleIndicator>()
            .setPath(TriangleIndicator.Path.NEGATIVE)
            .bind()
        // TriangleIndicator(w=10,h=10,p=NEGATIVE,g=top)
        tabLayout2.buildIndicator<TriangleIndicator>()
            .setPath(TriangleIndicator.Path.NEGATIVE)
            .setWidth(10.toPx())
            .setHeight(10.toPx())
            .setColor(ContextCompat.getColor(context!!,R.color.colorAccent))
            .setGravity(TabLayout.INDICATOR_GRAVITY_TOP)
            .bind()

    }
}
fragment_triangle_indicator.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp"
        android:text="TriangleIndicator"
        android:textColor="@color/colorDescription"
        android:textSize="12sp" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:paddingBottom="5dp"
        android:background="#F6F6F6"
        android:layout_gravity="center"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabIndicatorFullWidth="false"
        app:tabMode="scrollable"
        app:tabRippleColor="@android:color/transparent"
        app:tabSelectedTextColor="@color/colorAccent"
        app:tabTextColor="@color/colorSubtext" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="TriangleIndicator(p=NEGATIVE)"
        android:textColor="@color/colorDescription"
        android:textSize="12sp" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout1"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="#F6F6F6"
        android:layout_gravity="center"
        app:tabIndicatorColor="@color/colorTitle"
        app:tabIndicatorFullWidth="false"
        app:tabMode="scrollable"
        app:tabRippleColor="@android:color/transparent"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:text="TriangleIndicator(w=10,h=10,p=NEGATIVE,g=top)"
        android:textColor="@color/colorDescription"
        android:textSize="12sp" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout2"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:paddingTop="5dp"
        android:background="#F6F6F6"
        android:layout_gravity="center"
        app:tabIndicatorColor="@color/colorAccent"
        app:tabIndicatorFullWidth="false"
        app:tabMode="scrollable"
        app:tabRippleColor="@android:color/transparent"
        app:tabSelectedTextColor="@color/colorAccent"
        app:tabTextColor="@color/colorSubtext" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
3.自定义图片
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.loper7.tab_expand.ext.buildIndicator
import com.loper7.tab_expand.ext.buildText
import com.loper7.tab_expand.ext.toPx
import com.loper7.tab_expand.indicator.CustomIndicator
import com.loper7.tab_expand.text.BaseText
import com.loper7.tablayout_ext.R
import com.loper7.tablayout_ext.adapter.CustomFragmentAdapter
import kotlinx.android.synthetic.main.fragment_other_indicator.*


class CustomIndicatorFragment : Fragment() {
    var mRootView: View? = null
    private lateinit var adapter: CustomFragmentAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        if (mRootView == null) {
            mRootView = View.inflate(context, R.layout.fragment_other_indicator, null)
        }
        return mRootView
    }

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = CustomFragmentAdapter(childFragmentManager)
        viewPager.adapter = adapter
        tabLayout.setupWithViewPager(viewPager)

        // custom1
        tabLayout.buildIndicator<CustomIndicator>()
            .setDrawable(ContextCompat.getDrawable(context!!, R.mipmap.icon_indicator)!!)
            .setWidth(15.toPx())
            .setHeight(6.toPx())
            .bind()
        tabLayout.buildText<BaseText>()
            .setNormalTextBold(false)
            .setSelectTextBold(true)
            .setNormalTextSize(16f)
            .setSelectTextSize(18f)
            .bind()
    }
}
fragment_other_indicator.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:paddingBottom="5dp"
        android:background="#F6F6F6"
        app:tabIndicatorColor="#FFBB33"
        app:tabIndicatorFullWidth="false"
        app:tabMode="scrollable"
        app:tabRippleColor="@android:color/transparent"
        app:tabSelectedTextColor="@color/colorTitle"
        app:tabTextColor="@color/colorSubtext" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
adapter
import androidx.fragment.app.*
import com.loper7.tablayout_ext.fragment.LinearIndicatorFragment
import com.loper7.tablayout_ext.fragment.CustomIndicatorFragment
import com.loper7.tablayout_ext.fragment.TriangleIndicatorFragment

class MainFragmentAdapter(fm:FragmentManager) : FragmentStatePagerAdapter(fm) {

    override fun getCount(): Int {
        return 3
    }

    override fun getItem(position: Int): Fragment {
        return when(position){
            0->LinearIndicatorFragment()
            1-> TriangleIndicatorFragment()
            else->CustomIndicatorFragment()
        }
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return when(position){
            0-> "LINEAR"
            1-> "TRIANGLE"
            2-> "CUSTOM"
            else->""
        }
    }
}
import androidx.fragment.app.*
import com.loper7.tablayout_ext.SimpleFragment

class SimpleFragmentAdapter(fm:FragmentManager) : FragmentStatePagerAdapter(fm) {

    override fun getCount(): Int {
        return 6
    }

    override fun getItem(position: Int): Fragment {
        return SimpleFragment.newInstance("PAGE $position")
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return when(position){
            0-> "JAVA"
            1-> "OBJECT-C"
            2-> "FLUTTER"
            3-> "KOTLIN"
            4-> "SWIFT"
            5-> "REACT NATIVE"
            else-> "PHP"
        }
    }
}
import androidx.fragment.app.*
import com.loper7.tablayout_ext.SimpleFragment

class CustomFragmentAdapter(fm:FragmentManager) : FragmentStatePagerAdapter(fm) {

    override fun getCount(): Int {
        return 6
    }

    override fun getItem(position: Int): Fragment {
        return SimpleFragment.newInstance("PAGE $position")
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return when(position){
            0-> "直播"
            1-> "推荐"
            2-> "热门"
            3-> "追番"
            4-> "抗击肺炎"
            5-> "总之就是非常可爱"
            else-> "PHP"
        }
    }
}

SimpleFragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_simple.*

class SimpleFragment :Fragment() {
    var mRootView: View? = null

    companion object {
        fun newInstance(text: String): SimpleFragment {
            val args = Bundle()
            args.putString("text", text)
            val fragment = SimpleFragment()
            fragment.arguments = args
            return fragment
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        if (mRootView == null) {
            mRootView = View.inflate(context, R.layout.fragment_simple, null)
        }
        return mRootView
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        tv_text.text = requireArguments().getString("text")
    }
}

fragment_simple.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif-medium"
        android:text="TEXT"
        android:textColor="@color/colorTitle"
        android:textSize="18sp" />
</LinearLayout>![ic_indicator_fire.png](https://upload-images.jianshu.io/upload_images/22679253-7728493deed59ee9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![ic_indicator_index.png](https://upload-images.jianshu.io/upload_images/22679253-6efbee0bf5bb76dd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![ic_indicator_t.png](https://upload-images.jianshu.io/upload_images/22679253-803f822d21b4b94f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![icon_indicator.png](https://upload-images.jianshu.io/upload_images/22679253-a065cf65234f25e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![ic_indicator_finger.png](https://upload-images.jianshu.io/upload_images/22679253-923e14a7fccbed88.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

其他

tab_indicator_triangle_f.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="16dp"
    android:height="16dp"
    android:viewportWidth="100"
    android:viewportHeight="100">

    <path
        android:fillColor="#333333"
        android:pathData="m0 0 l50 50 l50 -50 z" />

</vector>

tab_indicator_triangle_z.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="16dp"
    android:height="16dp"
    android:viewportWidth="100"
    android:viewportHeight="100">

    <path
        android:fillColor="#333333"
        android:pathData="m50 0 l-50 50 l100 0 z" />

</vector>
icon_indicator.png
ic_indicator_finger.png
ic_indicator_fire.png
ic_indicator_index.png
ic_indicator_t.png

最后附上GitHub地址:https://github.com/loperSeven/tablayout-ext

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容