自定义View之文字绘制相关问题。

1. 自定义属性
  1. 在values下面新建一个attrs的文件
<resources>
    <!--name最好是自定义View的名字-->
     <!--name:名称;format:格式-->
        <!--字体大小,宽高 :dimension-->
        <!--reference :资源的引用-->
    <declare-styleable name="MyTextView">
    </declare-styleable>
</resources>

在具有两个参数的构造函数中拿到TypedArray,通过TypedArrayget×××()获取到自己在attrs中定义的属性值。具体代码如下:

 /*在布局中使用*/
    public MyTextView(Context context, @NonNull AttributeSet attrs) {
        this(context, attrs, 0);
       TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
      mText=typedArray.getString(R.styleable.MyTextView_myText);
        mTextColor=typedArray.getColor(R.styleable.MyTextView_myColor, mTextColor);
        mTextSize=typedArray.getDimensionPixelSize(R.styleable.MyTextView_myTextSize, mTextSize);
       /*回收*/
       typedArray.recycle();
    }

init():

  public MyTextView(Context context, @Nullable AttributeSet attrs, int
            defStyleAttr) {
        super(context, attrs, defStyleAttr);
        /*获取TypeArray*/
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
        mText=typedArray.getString(R.styleable.MyTextView_myText);
        mTextColor=typedArray.getColor(R.styleable.MyTextView_myColor, mTextColor);
        mTextSize=SizeUtils.sp2px(context,typedArray.getDimensionPixelSize(R.styleable
                        .MyTextView_myTextSize,
                mTextSize));
        /*回收*/
        typedArray.recycle();
        init();
    }

    private void init() {
        mTxtPaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTxtPaint.setColor(mTextColor);
        mTxtPaint.setTextSize(mTextSize);
        mTxtRect=new Rect();
        mTxtPaint.getTextBounds(mText,0,mText.length(),mTxtRect);
    }

在编辑textView的时候,wrapcontent是通过字的个数来进行绘制的。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode==MeasureSpec.AT_MOST){
            widthSize=mTxtRect.width()+ getPaddingLeft() +getPaddingRight();
        }
        if (heightMode==MeasureSpec.AT_MOST){
            heightSize=mTxtRect.height() + getPaddingTop() + getPaddingBottom();
        }

        setMeasuredDimension(widthSize,heightSize);
    }

注意如果在构造函数中使用的是this,那么所有的操作都是在第三个函数中进行操作:

 /*在代码中声明*/
    public MyTextView(Context context) {
        this(context, null);
    }
    /*在布局中使用*/
    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    /*使用style的时候会调用*/
    public MyTextView(Context context, @Nullable AttributeSet attrs, int
            defStyleAttr) {
        super(context, attrs, defStyleAttr);
        /*获取TypeArray*/
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
        mText=typedArray.getString(R.styleable.MyTextView_myText);
        mTextColor=typedArray.getColor(R.styleable.MyTextView_myColor, mTextColor);
        mTextSize=typedArray.getDimensionPixelSize(R.styleable.MyTextView_myTextSize, mTextSize);
        /*回收*/
        typedArray.recycle();
        init();
    }


在使用canvas画字体的时候,坐标轴很重要,是以左下角的点进行的,也就是说x坐标是getWeidth()-mTxtRect.width(),y坐标是getHeight();

2. 文字的绘制

  1. textview有一个很重要的点是baseline。
 //dy 代表的是:高度的一半到 baseLine的距离
        Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
        // top 是一个负值  bottom 是一个正值    top,bttom的值代表是  bottom是baseLine到文字底部的距离(正值)
        // 必须要清楚的,可以自己打印就好
        int dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
        int baseLine = getHeight()/2 + dy;

        int x = getPaddingLeft();

        canvas.drawText(mText,x,baseLine,mPaint);
  1. 其次是在onMeasure以及onDraw()中注意padding值。
  2. 在自定义java中,单位统一是像素,所以在自定义属性中获取的单位需要进行转化如:dp2px,sp2px等等。

3. 相关问题

1. 如果自定义view继承自ViewGroup(Linearlayout,Relativelayout等)会怎样:

默认的viewGroup不会触发onDraw()的,所以使用onDraw的相关方法会失效。 模板模式
调用draw(Canvas canvas)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值