view程序员

自定义 View 实战 01 - TextView

2020-06-15  本文已影响0人  Kotyo

前言

本来主要介绍了系统的textview是如何显示,字体大小、文字颜色如何设置、文字的位置该如何计算

步骤

1、继承 View 重写构造方法

class CustomTextView @JvmOverloads constructor(context: Context,attr: AttributeSet?,defStyle:Int=0) :View(context,attr,defStyle)

这里使用的是Kotlin,所以构造函数看起来要简洁很多

2、初始化对象及自定义参数获取

    var mPaint: Paint = Paint()
    var mText: String?
    var mTextSize = 0.0f
    var mTextColor = Color.BLACK

    init {
        val ta = context.obtainStyledAttributes(attr, R.styleable.CustomTextView)
        mText = ta.getString(R.styleable.CustomTextView_customText)
        mTextSize = ta.getDimensionPixelSize(
            R.styleable.CustomTextView_customTextSize,
            sp2Px(DEFAULT_TEXT_SIZE)
        ).toFloat()
        mTextColor = ta.getColor(R.styleable.CustomTextView_customTextColor, mTextColor)
        ta.recycle()

        mPaint.isAntiAlias = true
        mPaint.color = mTextColor
        mPaint.textSize = mTextSize
    }

3、重新 onMeasure()

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        var widthMode = MeasureSpec.getMode(widthMeasureSpec)
        var heightMode = MeasureSpec.getMode(heightMeasureSpec)
        var widthSize = MeasureSpec.getSize(widthMeasureSpec)
        var heightSize = MeasureSpec.getSize(heightMeasureSpec)

        if (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED) {//UNSPECIFIED:是为了兼容最外层是 ScrollView
            val rect = Rect()
            mPaint.getTextBounds(mText, 0, mText!!.length, rect)
            //实际宽度 = 文字宽度 + view 的左右 padding 
            widthSize = rect.width() + paddingLeft + paddingRight
        }

        if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {//UNSPECIFIED:是为了兼容最外层是 ScrollView
            val fontMetricsInt = mPaint.fontMetricsInt
            //实际高度 = 文字高度 + view 的上下 padding
            heightSize  = fontMetricsInt.bottom-fontMetricsInt.top + paddingLeft + paddingRight
        }
        //一定要设置,这步是为了将测量好的宽高设置给 view
        setMeasuredDimension(widthSize, heightSize)
    }

MeasureSpec 包括了 mode(测量模式)、size(测量大小)

`mode`                       xml
AT_MOST                  WRAP_CONTENT
EXACTLY                  固定的值(50dp)或 MATCH_PARENT
UNSPECIFIED              无(一般系统内部使用)

4、重写 onDraw() 方法

override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        val fontMetricsInt = mPaint.fontMetricsInt
        //bottom 和 top 是到 baseLine 的距离(bottom 为正,top 为负)
        val dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom
        //vY 是文字的基线值
        val vY = height / 2 + dy
        canvas?.drawText(mText!!, paddingLeft.toFloat(), vY.toFloat(), mPaint)
    }
参数说明
<com.black.multi.customviewsample.demo01.CustomTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:paddingLeft="10dp"
            android:paddingRight="20dp"
            android:paddingTop="5dp"
            android:paddingBottom="10dp"
            app:customText="我是自定义CustomTextView"
            app:customTextColor="@color/colorPrimary"
            app:customTextSize="16sp" />
自定义TextView

好了,到这里就结束了,简单的几步就可以实现文字的展示了,自定义 View 的基本步骤就如上面介绍的那样。这里总结一下:

项目地址

上一篇 下一篇

猜你喜欢

热点阅读