依赖库:implementation 'com.google.android.material:material:1.4.0'

改变TabLayout的指示器

将Indicator的宽度设置成和文字宽度一样

使用28及以上的SDK,在布局中为TabLayout添加属性app:tabIndicatorFullWidth="false"

自定义Indicator,包括色值、宽高等等

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <item android:gravity="center">
        <shape>
            <size android:width="20dp"
                android:height="4dp"/>
            <solid android:color="@android:color/holo_red_light"/>
        </shape>
    </item>
</layer-list>

<android.support.design.widget.TabLayout
    android:id="@+id/tl_style_one_tab"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:tabIndicatorColor="@color/common_transparent"
    app:tabIndicator="@drawable/tab_indicator"/>

注意:tabIndicatorColor要设置为透明,不然看不到自己设置的效果

改变TabLayout中的文字的粗细(选中的时候加粗,不选中的时候变细)

tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
      override fun onTabSelected(tab: TabLayout.Tab?) {
        if (tab == null) return
        TabLayoutHelper.getTabTextView(tab)?.setTextAppearance(context, R.style.room_OnlineMemberTabLayoutTheme_bold)
      }

      override fun onTabUnselected(tab: TabLayout.Tab?) {
        if (tab == null) return
        TabLayoutHelper.getTabTextView(tab)?.setTextAppearance(context, R.style.room_OnlineMemberTabLayoutTheme)
      }

      override fun onTabReselected(tab: TabLayout.Tab?) {

      }

    })

为TabLayout中的文字设置小红点

object TabLayoutHelper {

  private const val TAG = "TabLayoutHelper"

  fun getTabTextView(tab: TabLayout.Tab): TextView? {
    return try {
      val tabView = tab.view
      val tabTextViewField = TabLayout.TabView::class.java.getDeclaredField("textView")
      tabTextViewField.isAccessible = true
      tabTextViewField.get(tabView) as TextView
    } catch (e: Exception) {
      loge(TAG, e)
      null
    }
  }

  fun addDrawableEnd(context: Context, tab: TabLayout.Tab, drawableEndResId: Int) {
    try {
      val tabTextView = getTabTextView(tab) ?: return
      tabTextView.compoundDrawablePadding = 2.dp
      val drawable = ContextCompat.getDrawable(context, drawableEndResId)
      drawable?.let {
        it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)
        tabTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, it, null)
      }
    } catch (e: Exception) {
      loge(TAG, e)
    }
  }

  fun removeDrawableEnd(tab: TabLayout.Tab) {
    try {
      val tabTextView = getTabTextView(tab) ?: return
      tabTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null)
    } catch (e: Exception) {
      loge(TAG, e)
    }
  }

}

TabLayout文字左右切换动画示例

注意:这里就没有用TabLayout,而是自定义了两个TextView

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/ll_tab"
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="51dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/tv_favourite"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/room_string_favourite"
            android:textColor="@color/grey_9a9aa4"
            android:textSize="16dp"
            app:layout_constraintBaseline_toBaselineOf="@id/tv_recommend"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tv_recommend"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="14dp"
            android:text="@string/room_string_recommend"
            android:textColor="@color/black_121214"
            android:textSize="21dp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@id/tv_favourite"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
class SimpleTabTextChangeCallback(
  private var fontMaxPx: Int,
  private var fontMinPx: Int,
  private var colorNormal: Int,
  private var colorSelect: Int,
  private var viewNormalDefault: TextView,
  private var viewSelectDefault: TextView,
  private var onPageSelected: (callback: SimpleTabTextChangeCallback, position: Int) -> Unit
) : ViewPager2.OnPageChangeCallback() {
  
  private val TAG = "TabTextChangeCallback"
  private var argbEvaluator = ArgbEvaluator()
  private var lastPositionOffset = 0f
  private var fontDiff = fontMaxPx - fontMinPx
  private var byDrag = false //避免第一次进入页面出现的动画效果
  
  override fun onPageScrollStateChanged(state: Int) {
    when (state) {
      ViewPager2.SCROLL_STATE_IDLE -> { //停止滑动,保证字体大小无误
        byDrag = false
        if (viewNormalDefault.textSize > viewSelectDefault.textSize) {
          viewNormalDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMaxPx.toFloat())
          viewSelectDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMinPx.toFloat())
        } else {
          viewNormalDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMinPx.toFloat())
          viewSelectDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMaxPx.toFloat())
        }
      }
      ViewPager2.SCROLL_STATE_DRAGGING -> { //拖拽中
        byDrag = true
      }
      ViewPager2.SCROLL_STATE_SETTLING -> { //惯性滑动中

      }
    }
  }
  override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
    if (!byDrag || positionOffset <= 0 || positionOffset > 1 || abs(positionOffset - lastPositionOffset) < 0.05) return //过滤异常数据 && 避免抖动
    if (positionOffset > lastPositionOffset) { //从右往左滑动
      viewNormalDefault.setTextColor(argbEvaluator.evaluate(positionOffset, colorSelect, colorNormal) as Int)
      viewNormalDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMaxPx - fontDiff * positionOffset)
      viewSelectDefault.setTextColor(argbEvaluator.evaluate(positionOffset, colorNormal, colorSelect) as Int)
      viewSelectDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMinPx + fontDiff * positionOffset)
    } else { //从左往右滑动
      viewNormalDefault.setTextColor(argbEvaluator.evaluate(1 - positionOffset, colorNormal, colorSelect) as Int)
      viewNormalDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMinPx + fontDiff * (1 - positionOffset))
      viewSelectDefault.setTextColor(argbEvaluator.evaluate(1 - positionOffset, colorSelect, colorNormal) as Int)
      viewSelectDefault.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMaxPx - fontDiff * (1 - positionOffset))
    }
    lastPositionOffset = positionOffset
    logi(TAG, "position = $position, positionOffset = $positionOffset, positionOffsetPixels = $positionOffsetPixels")
  }
  override fun onPageSelected(position: Int) {
    onPageSelected.invoke(this@SimpleTabTextChangeCallback, position)
  }

  fun onTabSelect() {
    setTabSelect(viewNormalDefault)
    setTabUnSelect(viewSelectDefault)
    //
    (viewNormalDefault.layoutParams as ConstraintLayout.LayoutParams).apply {
      baselineToBaseline = ConstraintLayout.LayoutParams.UNSET
      bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
    }
    (viewSelectDefault.layoutParams as ConstraintLayout.LayoutParams).apply {
      baselineToBaseline = viewNormalDefault.id
      bottomToBottom = ConstraintLayout.LayoutParams.UNSET
    }
  }

  fun onTabUnSelect() {
    setTabSelect(viewSelectDefault)
    setTabUnSelect(viewNormalDefault)
    //
    (viewNormalDefault.layoutParams as ConstraintLayout.LayoutParams).apply {
      baselineToBaseline = viewSelectDefault.id
      bottomToBottom = ConstraintLayout.LayoutParams.UNSET
    }
    (viewSelectDefault.layoutParams as ConstraintLayout.LayoutParams).apply {
      baselineToBaseline = ConstraintLayout.LayoutParams.UNSET
      bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
    }
  }

  private fun setTabSelect(textView: TextView) {
    textView.apply {
      setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMaxPx.toFloat())
      setTextColor(colorSelect)
      typeface = Typeface.defaultFromStyle(Typeface.BOLD)
    }
  }

  private fun setTabUnSelect(textView: TextView) {
    textView.apply {
      setTextSize(TypedValue.COMPLEX_UNIT_PX, fontMinPx.toFloat())
      setTextColor(colorNormal)
      typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
    }
  }
}

使用如下

tabTextChangeCallback = SimpleTabTextChangeCallback(21.dp, 16.dp,
  resources.getColor(R.color.grey_9a9aa4), resources.getColor(R.color.black_121214),
  leftTextView, rightTextView) { callback, position ->
  if (position == RoomPagerType.TYPE_FAVORITED) {
    callback.onTabSelect()
  } else {
    callback.onTabUnSelect()
  }
}
viewPager.registerOnPageChangeCallback(tabTextChangeCallback)

添加新评论