一、View组件
View组件有几个重要的方法需要关注,也是自定义View经常需要重写的方法。

1、measure
作用是测量View组件的尺寸。对应的方法是onMeasure,测量View的宽和高。View和 ViewGroup都有measure方法,但ViewGroup除了测量自身尺寸,还要遍历地调用子元素的measure方法。

2、layout
用于确定布局位置。对应的方法是layout、onLayout,用于确定元素的位置,ViewGroup中的layout方法用来确定子元素的位置。

3、draw
作用是绘制内容背景,包括View的内容、子View的内容和背景。具体方法包括:drawBackground、onDraw、ViewGroup.dispatchDraw。

这个方法有个关键的入参也是唯一的入参:Canvas。其在native层有个对应的画布组件SkCanvas,该组件内部封装的SkBitmap实现了类似画纸的功能。

在Android系统中,View.draw的部分实现如下:

        // Step 1, draw the background, if needed
        int saveCount;       
        if (!dirtyOpaque) {
            drawBackground(canvas);
        }         // skip step 2 & 5 if possible (common case)
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        
if (!verticalEdges && !horizontalEdges) {
            // Step 3, draw the content          
            if (!dirtyOpaque) {
                long logTime = System.currentTimeMillis();
                onDraw(canvas);                
            }
            ...             // Step 4, draw the children
            dispatchDraw(canvas);
            drawAutofilledHighlight(canvas);             // Overlay is part of the content and draws beneath Foreground
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }             // Step 6, draw decorations (foreground, scrollbars)
            onDrawForeground(canvas);

其中绘制背景的实现,是通过Drawable类型的变量mBackground也就是背景图来完成的。View中的onDraw是个空方法,但在具体的View组件例如ImageView中,都会有对应的扩展实现。

这里的绘制,主体功能通常是Drawable和Canvas,后者处理绘制区域、矩阵变换等工作,前者根据组件功能,实现具体绘制操作,例如BitmapDrawable中的draw方法,最终是通过Paint画笔组件和Canvas的drawBitmap方法实现绘制操作的。

对于自定义视图组件,通常需要重写onDraw方法,并在该方法中调用Canvas的drawXXX例如drawBitmap、drawText等方法来实现预期的效果,如果涉及到几何变换,还可能会用到Matrix组件。

二、Canvas组件
作为绘制处理中的画布组件,Canvas提供了裁剪区域/路径和多种图形/图像绘制功能,对应的方法有:

  • clipRect、clipPath、clipRegion;
  • drawBitmap、drawTex、drawLine;

具体实现都是在native层完成的,涉及SkiaCanvas、SkCanvas。

    public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
        checkValidClipOp(op);
        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
    }

在framework层的android_graphics_Canvas.cpp中,有对应实现:


static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
                         jfloat r, jfloat b, jint opHandle) {
    bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
            opHandleToClipOp(opHandle));
    return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
}

该方法会调用到SkiaCanvas.cpp中的实现,这里先不展开分析。

三、融合与思考

1、Activity、Window和View之间关系
1)Window和PhoneWindow
PhoneWindow类,派生于Window,是连接Activity跟View的桥梁,所有Activity对View的操作都需要借助它。

2)Activity和Window
在Activity启动过程中,系统会调用attach方法,并创建PhoneWindow实例;之后,在具体Activity的onCreate函数中,通常都会调用setContentView方法,进而调用PhoneWindow的setContentView方法设置DecorView。

3)Window和View
Window通过WindowManagerImp类型的成员变量mWindowManager操作View。WindowManagerImpl是WindowManager接口的具体实现,该类通过WindowManagerGlobal完成addView、removeView、updateViewLayout这三个方法。
进一步地,PhoneWindow的成员变量DecorView,可以通过getViewRootImpl方法获取ViewRoot实例。与之对应的ViewRootImpl类,有个IWindowSession类型的成员变量mWindowSession,能够访问WMS。

小结:PhoneWindow类,是连接Activity跟View的桥梁;而ViewRootImpl是 View 和 WindowMangerService之间的桥梁。

(相关完整且成体系的文章,可参见本人原创的开源电子书《Android系统与性能优化》,地址:https://github.com/carylake/androidnotes)

最新文章

  1. SVN提交时响应很慢,我是这样解决的。
  2. 01-Swift 介绍
  3. c++关于析构的那点小事(个人吐槽向
  4. JQuery冲突问题,以及含有jquery的框架与jquery冲突
  5. Owin中间件搭建OAuth2.0认证授权服务体会
  6. ActiveMQ持久化消息
  7. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)
  8. C#结构函数与base关键字
  9. DotNetCore跨平台~认识环境和环境变量
  10. 土制Excel导入导出及相关问题探讨
  11. UE、UI、UCD、UED?职责划分?
  12. String painter HDU - 2476 -区间DP
  13. Mybatis调用PostgreSQL存储过程实现数组入参传递
  14. 关于java异常处理的自我学习
  15. Xshell存在后门
  16. 要想找出包含“w”的名字
  17. placeholder的使用
  18. app 图标规格参考表
  19. python random模块(获取随机数)的常用方法及示例
  20. css实现水平 垂直居中

热门文章

  1. json序列化反序列化Jackson相关注解
  2. 2019-2020-11 20199304 《Linux内核原理与分析》 第十二周作业
  3. 关于token你需要知道的【华为云技术分享】
  4. gitbook 入门教程之增强版 edit-link-plus 编辑此页插件
  5. 大数据之Linux服务器集群搭建
  6. ARTS-S ansible-playbook
  7. Day 03 Python 基础
  8. 【CSS】329- 非常强!3行核心css代码的rate评分组件
  9. Shell排序 C&&C++
  10. Element UI 源码—— Carousel 走马灯学习