当前位置:   article > 正文

Android TextView 字体大小&组件高度自适应解决方案_textview自适应高度

textview自适应高度

TextView字体大小与组件高度不匹配问题

通常在做UI的时候,文本都是比较重要的一部分。

但是在Android中,往往会出现实际效果与UI图不太一致的情况,导致这种情况的出现主要是以下3个点。

问题点

属性值与实际绘制测量结果不一致

  • 字体大小
  • 字体行高
  • 组件高度

解决方案

  • 自定义行高属性,严格遵从定义数值
  • 通过文本行数x行高,重新计算组件高度
  • 根据给定字号,在行高范围内,自适应调整字体高度不会超过行高,再重新设置字号大小

具体代码实现

package cc.xiaobaicz.playground.widgets

import android.content.Context
import android.graphics.Paint.FontMetrics
import android.os.Build
import android.text.StaticLayout
import android.util.AttributeSet
import android.util.TypedValue
import androidx.appcompat.widget.AppCompatTextView
import cc.xiaobaicz.playground.R
import kotlin.math.max

/**
 * TextView
 * 1\. 行高适配
 * @author xiaobai
 */
class Text : AppCompatTextView {

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, android.R.attr.textViewStyle)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        isFallbackLineSpacing = false
        val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.Text, defStyleAttr, 0)
        lineHeight = typedArray.getDimension(R.styleable.Text_lineHeightX, textSize).toInt()
        typedArray.recycle()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            // 重新计算高度,适应多行文本
            val layout = StaticLayout.Builder.obtain(text, 0, text.length, paint, measuredWidth).build()
            val height = lineHeightX * layout.lineCount + paddingTop + paddingBottom
            setMeasuredDimension(measuredWidth, height)
        }
    }

    override fun setFallbackLineSpacing(enabled: Boolean) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return
        super.setFallbackLineSpacing(false)
    }

    var lineHeightX: Int = 0
        private set

    override fun setLineHeight(lineHeight: Int) {
        lineHeightX = max(lineHeight, 8)
        adaptiveTextSize()
        super.setLineHeight(lineHeightX)
        requestLayout()
        invalidate()
    }

    private fun adaptiveTextSize() {
        var metrics = paint.fontMetrics
        while (metrics.fontHeight > lineHeightX) {
            paint.textSize -= max((metrics.fontHeight - lineHeightX) / 2, 1f)
            metrics = paint.fontMetrics
        }
        setTextSize(TypedValue.COMPLEX_UNIT_PX, paint.textSize)
    }

    private val FontMetrics.fontHeight: Float get() = descent - ascent

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

转载:https://www.jianshu.com/p/ccea88e33ebc

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/543914
推荐阅读
相关标签
  

闽ICP备14008679号