美文网首页源码原理知识点
自定义View_03_(入门篇)TextView的基线计算&测量

自定义View_03_(入门篇)TextView的基线计算&测量

作者: __Y_Q | 来源:发表于2019-12-18 09:20 被阅读0次
    前两个章节只是简单的说了下自定义属性及使用, 这章会完整的绘制出一个我们自己定义的TextView出来.
    1. 布局文件设置
        <com.view_day02.MyTextView
            android:padding="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:myInputType="text"
            app:myTextSize="20sp"
            app:myText="zhangsan"
            android:background="#00FF00"
            app:myTextColor="#000000"/>
    
    2. 创建画笔
        private String mText;
        private int mTextSize = 15;
        private int mTextColor = Color.BLACK;
    
        // 画笔
        private Paint mPaint;
    
        public MyTextView(Context context) {
            this(context, null);
        }
    
        public MyTextView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            // 获取自定义属性
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
            mText = typedArray.getString(R.styleable.MyTextView_myText);
            mTextColor = typedArray.getColor(R.styleable.MyTextView_myTextColor, mTextColor);
            mTextSize = typedArray.getDimensionPixelSize(R.styleable.MyTextView_myTextSize, sp2px(mTextSize));
           
            // 回收
            typedArray.recycle();
    
            initPaint();
        }
         private int sp2px(int sp) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
        }
        //初始化画笔
        private void initPaint() {
            mPaint = new Paint();
            // 抗锯齿
            mPaint.setAntiAlias(true);
            // 设置画笔绘制文字的大小
            mPaint.setTextSize(mTextSize);
            // 设置画笔颜色
            mPaint.setColor(mTextColor);
        }
    
    3. 开始测量onMeasure
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    
            // 获取宽高的模式,是dp,还是 wrap_content/match_parent
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            
            //有以下三种模式
            //MeasureSpec.AT_MOST 在布局中指定了 wrap_content
            //MeasureSpec.EXACTLY 在布局中指定了确切的值, 或是match_parent/fill_parent
            //MeasureSpec.UNSPECIFIED 尽可能的大 (很少用到)
            
            // 1. 如果宽高是确定的值,这个时候不需要计算.给多少就是多少.
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
    
            // 2. 如果是wrap_content. 需要计算
            if (widthMode == MeasureSpec.AT_MOST) {
                // 计算宽度. 宽度与字体的长度,大小有关. 需要用画笔来测量
                Rect bounds = new Rect();
                // 获取文本的 Rect, 把结果返回至最后一个参数 bounds
                mPaint.getTextBounds(mText, 0, mText.length(), bounds);
                //因为设置了padiing,所以需要加上 padding 的 left 和 right
                widthSize = bounds.width() + getPaddingLeft() + getPaddingRight();
            }
            if (heightMode == MeasureSpec.AT_MOST) {
                Rect bounds = new Rect();
                mPaint.getTextBounds(mText, 0, mText.length(), bounds);
                //因为设置了padiing,所以需要加上padding的top和bottom
                heightSize = bounds.height() + getPaddingTop() + getPaddingBottom();
            }
    
            // 设置自定义TextView的宽高
            setMeasuredDimension(widthSize, heightSize);
        }
    
    4. 测量完成后,开始用画笔画
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
            //dy 代表在是 高度的一半到BaseLine 的距离
            //fontMetrics.top 是baseLine到顶部的距离(负值)
            //fontMetrics.bottom  baseLine到底部的距离(正值)
            float dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            float baseLine = getHeight() / 2 + dy;
            int  x = getPaddingLeft();  //重新加上paddingLeft
            // drawText 参数说明
            // text,
            // x(开始的位置),
            // y(基线-baseLine) 需要求BaseLine,网上有介绍基线的介绍,这里就不再说明
            // ,paint
            canvas.drawText(mText, x, baseLine, mPaint);
        }
    

    求 TextView 基线算法,了解基线后直接套公式即可

    float dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
    float baseLine = getHeight() / 2 + dy;
    

    相关文章

      网友评论

        本文标题:自定义View_03_(入门篇)TextView的基线计算&测量

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