美文网首页
TabItem的定制思路及实现

TabItem的定制思路及实现

作者: 小强开学前 | 来源:发表于2020-07-15 15:48 被阅读0次

安卓上一直没有上图片下文字的组件,即使是谷歌的BottomNavigationBar,也只能是一整个控件,而且横竖屏都是一个样式,不能定制。其实这也怪国内设计师没想法,人苹果怎么来UI就怎么画。

实现效果

需求

  • 图片
  • 文字
  • 红点(消息推送)

定义及获取

背景不需要指定,只需要在TabBar指定就行,TabBar将TabItem作为子控件。

1. 图片

  • 定义
private var tabIcon: Drawable? = null
  • 格式
<attr name="tab_icon" format="reference"/>
  • 获取
tabIcon = ta.getDrawable(R.styleable.TabItem_tab_icon)

传入的是selector类型的xml?没问题,它是StateListDrawable,是Drawable的子类。仍然正常接收,状态切换的话。
翻了下ImageView的源码,easy,就是在回调中设置下view的状态就行了。

override fun drawableStateChanged() {
    super.drawableStateChanged()
    tabIcon?.let { icon ->
        icon.setState(drawableState).takeIf { icon.isStateful }
    }
    // 为保证文字颜色也会改变,统一重新绘制
    invalidate()
}

2. 文字

  • 定义
private var tabTitle: String = ""
  • 格式
<attr name="tab_title" format="string"/>
  • 获取
tabTitle = ta.getString(R.styleable.TabItem_tab_title) ?: "Tab"

太简单了,不说了。

3. 红点

  • 定义
    var showBadge: Boolean = false
    private var badgeSize: Int = if (isInEditMode) 8 else 6.dp.toInt()

badgeSize可以从xml读取,showBadge直接从外部设置就行。

实现

重写onDraw方法即可

override fun onDraw(canvas: Canvas?) {
    // 设置字体大小
    textPaint.textSize = tabTitleSize
    // 获取文字宽度
    val titleWidth = textPaint.measureText(tabTitle)
    // 获取文字高度
    val titleHeight = textPaint.fontMetrics.bottom - textPaint.fontMetrics.top
    canvas?.let {
        // 确定文字的left、top
        // left、right左右居中
        titleL = (measuredWidth - titleWidth) / 2f
        // 无icon上下居中,有icon,加上icon高度和间距再居中
        titleT = (measuredHeight - titleHeight + (0.takeIf { intrinsicHeight == 0 } ?: (intrinsicHeight + iconPadding))) / 2f
        tabIcon?.let { icon ->
            // 确定图片的left、top、right、bottom
            iconL = (measuredWidth - intrinsicWidth) / 2
            iconR = iconL + intrinsicWidth
            // padding+图片高度+文字高度之后 图的位置
            iconT = (measuredHeight - titleHeight.toInt() - (0.takeIf { intrinsicHeight == 0 } ?: (iconPadding + intrinsicHeight))) / 2
            iconB = iconT + intrinsicHeight
            drawDrawable(icon, it)
            if (showBadge) drawBadge(it)
        }
        drawTitle(it, titleHeight.toInt())
    }
}

具体代码及实现可以参考我的Github页面

相关文章

网友评论

      本文标题:TabItem的定制思路及实现

      本文链接:https://www.haomeiwen.com/subject/cswdhktx.html