ViewGroup默认不触发onDraw()方法源码分析

首先我们思考一个问题:

如果我们按照如下的方式自定义TextView,会有显示吗?

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--name 自定义View的名字 TextView-->
    <declare-styleable name="MyTextView">
        <!-- name 属性名称

        format 格式: string 文字  color 颜色
                    dimension 宽高 字体大小  integer 数字
                    reference 资源(drawable)
         -->
        <attr name="lzyText" format="string"/>
        <attr name="lzyTextColor" format="color"/>
        <attr name="lzyTextSize" format="dimension"/>
        <attr name="lzyMaxLength" format="integer"/>

        <!-- 枚举 -->
        <attr name="lzyInputType">
            <enum name="number" value="1"/>
            <enum name="text" value="2"/>
            <enum name="password" value="3"/>
        </attr>

    </declare-styleable>

</resources>
public class MyTextView extends LinearLayout {

    private String mText;
    private int mTextColor;
    private int mTextSize;
    private Paint mPaint;

    //构造函数在代码new的时候调用
    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);
        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
        mText = a.getString(R.styleable.MyTextView_lzyText);
        mTextColor = a.getColor(R.styleable.MyTextView_lzyTextColor, Color.BLACK);
        mTextSize = a.getDimensionPixelSize(R.styleable.MyTextView_lzyTextSize,20);
        a.recycle();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(mTextSize);
        mPaint.setColor(mTextColor);


    }

    //布局的宽高都是有这个方法指定
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取宽高的模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int width = MeasureSpec.getSize(widthMeasureSpec);
        if (widthMode == MeasureSpec.AT_MOST){
            Rect rect = new Rect();
            mPaint.getTextBounds(mText,0,mText.length(),rect);
            width = rect.width();
        }

        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode == MeasureSpec.AT_MOST){
            Rect r = new Rect();
            mPaint.getTextBounds(mText,0,mText.length(),r);
            height = r.height();
        }

        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint.FontMetricsInt fontMetricsInt = mPaint.getFontMetricsInt();
        int dy = 0;
        dy = (fontMetricsInt.bottom - fontMetricsInt.top)/2 - fontMetricsInt.bottom;
        int baseLine = getHeight()/2 + dy;
        canvas.drawText(mText,0,baseLine,mPaint);
    }

}
 <com.example.michael.view_01.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:lzyText="hello world"
        app:lzyTextColor="@color/colorAccent"
        app:lzyTextSize="20sp"
        />

当我们运行模拟器是,效果是这样的:

效果并没有出来,为什么我们自定义的TextView继承了一个ViewGroup效果就没有了呢?

draw(Canvas canvas)

我们再View的源码里面看draw()方法:

if (!dirtyOpaque) onDraw(canvas);

可见dirtyOpaque为false时,onDraw()方才会调用。

final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

直接继承View会走onDraw()方法说明dirtyOpaque确实运算后会false。

下面我们来看ViewGroup的构造方法:

public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        initViewGroup();
        initFromAttributes(context, attrs, defStyleAttr, defStyleRes);
    }

进到initViewGroup()里面:这样dirtyOpaque会被重新赋值。

 

setFlags(WILL_NOT_DRAW, DRAW_MASK);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AD钙奶-lalala

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值