美文网首页view程序员
自定义 View 实战 01 - TextView

自定义 View 实战 01 - TextView

作者: Kotyo | 来源:发表于2020-06-15 11:19 被阅读0次

    前言

    本来主要介绍了系统的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 的基本步骤就如上面介绍的那样。这里总结一下:

    • 重新构造函数(初始化会需要)
    • 对象初始化及自定义属性的获取
    • 重写 onMeasure() 方法(只有重新了该方法,绘制的内容才能正确的显示)
    • 重写 onDraw() 方法(在这里绘制我们需要的内容,调用各种 drawXXX() 方法)

    项目地址

    相关文章

      网友评论

        本文标题:自定义 View 实战 01 - TextView

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