摘要:HenCoder Android 开发进阶:自定义 View 1-5 绘制顺序

前面几期讲的是「术」,是「用哪些 API 可以绘制什么内容」。
接下来要讲的是「道」,是「怎么去安排这些绘制」。

这期是「道」的第一期:绘制顺序。

1 super.onDraw() 前 or 后?
前几期我写的自定义绘制,全都是直接继承 View 类,然后重写它的 onDraw() 方法,把绘制代码写在里面,就像这样:

public class AppView extends View {

protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

… // 自定义绘制代码
}

}
这是自定义绘制最基本的形态:继承 View 类,在 onDraw() 中完全自定义它的绘制。
在 View.java 的源码中,onDraw() 是空的
然而,除了继承 View 类,自定义绘制更为常见的情况是,继承一个具有某种功能的控件,
去重写它的 onDraw() ,在里面添加一些绘制代码,做出一个「进化版」的控件
这种基于已有控件的自定义绘制,就不能不考虑 super.onDraw() 了:
你需要根据自己的需求,判断出你绘制的内容需要盖住控件原有的内容还是需要被控件原有的内容盖住,
从而确定你的绘制代码是应该写在 super.onDraw() 的上面还是下面

1.1 写在 super.onDraw() 的下面
把绘制代码写在 super.onDraw() 的下面,由于绘制代码会在原有内容绘制结束之后才执行,所以绘制内容就会盖住控件原来的内容。

这是最为常见的情况:为控件增加点缀性内容。比如,在 Debug 模式下绘制出 ImageView 的图像尺寸信息
public class AppImageView extends ImageView {

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (DEBUG) {
        // 在 debug 模式下绘制出 drawable 的尺寸信息
        ...
    }
}

}

1.2 写在 super.onDraw() 的上面
如果把绘制代码写在 super.onDraw() 的上面,由于绘制代码会执行在原有内容的绘制之前,所以绘制的内容会被控件的原内容盖住。

相对来说,这种用法的场景就会少一些。不过只是少一些而不是没有,比如你可以通过在文字的下层绘制纯色矩形来作为「强调色」:

public class AppTextView extends TextView {

protected void onDraw(Canvas canvas) {
 ... // 在 super.onDraw() 绘制文字之前,先绘制出被强调的文字的背景

    super.onDraw(canvas);
}

}

2 dispatchDraw():绘制子 View 的方法
讲了这几期,到目前为止我只提到了 onDraw() 这一个绘制方法。
但其实绘制方法不是只有一个的,而是有好几个,其中 onDraw() 只是负责自身主体内容绘制的。
而有的时候,你想要的遮盖关系无法通过 onDraw() 来实现,而是需要通过别的绘制方法。

    例如,你继承了一个 LinearLayout,重写了它的 onDraw() 方法,
    在 super.onDraw() 中插入了你自己的绘制代码,使它能够在内部绘制一些斑点作为点缀:
    public class SpottedLinearLayout extends LinearLayout {
           ...
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            ... // 绘制斑点
        }
    }

    但是你会发现,当你添加了子 View 之后,你的斑点不见了:

猜你喜欢

转载自blog.csdn.net/qq_27073205/article/details/80226975
今日推荐