自定义View-绘制顺序

前言

Android里面的绘制都是按顺序的,先绘制的会被后绘制的盖住。我们要学会实现自己所需要的遮盖关系

super.onDraw()

// 直接继承View的话,是无所谓的,因为onDraw()方法是空实现

// 继承某一个已知的控件,就有分别了
    // super.onDraw()下面:绘制内容覆盖原有内容,比如打印图像尺寸信息
    // super.onDraw()上面:绘制内容被原有内容覆盖,比如给TextView加一个底色

dispatchDraw()

// 子View的绘制会遮盖ViewGroup的绘制,所以在onDraw()无法实现遮盖子View
// dispatchView()只对ViewGroup有意义
    // super.dispatchDraw()下面:可以盖住子View
    // super.dispatchDraw()上面:和在onDraw()下面写的效果是一样的

绘制过程简述


// 背景:无法重写
drawBackground()

// 主体:我们常重写的
onDraw()

// 绘制子View的方法
dispatchDraw()

// 滑动边缘渐变和滑动条、前景
onDrawForeground()

注意:前景的支持是在android6.0之后,之前只支持FrameLayout

onDrawForeground()

// 此方法是在API23的时候才引入的,此方法会依次绘制滑动边缘渐变、滑动条和前景
    // super.onDrawForeground()下面:盖住滑动边缘渐变、滑动条、前景
    // super.onDrawForeground()上面:盖住子View,但被滑动边缘渐变、滑动条、前景盖住

// 注意:想在滑动边缘渐变、滑动条和前景之间插入绘制代码?  NoNoNo,不可以的


draw()总调度方法

// 大致的一个结构
public void draw(Canvas canvas) {  
    ...

    drawBackground(Canvas); // 绘制背景(不能重写)
    onDraw(Canvas); // 绘制主体
    dispatchDraw(Canvas); // 绘制子 View
    onDrawForeground(Canvas); // 绘制滑动相关和前景

    ...
}


// super.draw()下面:会盖住所有的绘制内容
// super.draw()上面:被所有其他内容盖住,比如,在背景下加一个下划线

注意点:

// 出于效率的考虑,ViewGroup默认会绕过draw()方法,换而直接执行dispatchDraw()方法,以此来简化绘制流程。在除dispatchDraw()以外的方法绘制内容,可能需要调用View.setWillNotDraw(false)来切换的完整的绘制流程,但有些ViewGroup已经调用过此方法了,比如ScrollView



// 如果绘制代码既可以写在onDraw()里, 也可以写在其他绘制方法里, 那么优先写在onDraw(),因为Android有相关的优化,可以在不需要重绘的时候自动跳过onDraw()的重复执行,以提升开发效率

总结

其实只要牢记draw()的调度就OK了,剩下在前在后,只不过代码执行顺序的问题而已了,很好记忆

贴个HenCoder的链接:自定义View-绘制顺

分割线---------------------------------------------------------------------------------

实践

// 1 图片上打印尺寸信息, onDraw()后插
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // todo 打印尺寸信息
    }



// 2 给TextView绘制黄色背景, onDraw()前插
    @Override
    protected void onDraw(Canvas canvas) {
        // todo 绘制黄色背景
        super.onDraw(canvas);
    }



// 3 画粉色斑点
    // 记得调用setWillNotDraw(false)以启动完整的绘制流程;



// 4 让绘制的粉色斑点盖住子View
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        // todo 绘制粉色斑点
    }



// 5 绘制的标签盖住黑色前景, onDrawForeground()后插
    @Override
    public void onDrawForeground(Canvas canvas) {
        super.onDrawForeground(canvas);
        // todo 绘制标签
    }  



// 6 绘制的标签被前景盖住, onDrawForeground()前插
    @Override
    public void onDrawForeground(Canvas canvas) {
        // todo 绘制标签
        super.onDrawForeground(canvas);        
    }



// 7 盖在其他所有, draw()方法后插     
    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        // todo 绘制标签
    }



// 8 编辑框的背景就是下划线的情况下, 在下划线下再加一层背景, draw()方法前插
    @Override
    public void draw(Canvas canvas) {
        // todo 绘制背景
        super.draw(canvas);      
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值