一、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)

Android组件体系之视图绘制的更多相关文章

  1. Android组件体系之BroadcastReceiver小结

    1.常见分类    BroadCastReceiver,按注册方式可以分为静态广播接收器和动态广播接收器.    静态广播接收器:不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播(一般广 ...

  2. Android组件体系之ContentProvider使用注意事项

    1.数据访问机制 客户端/调用者通过getContentResolver调用,由ActivityThread.AMS获取到ContentProvider的代理,再通过这个代理对象调用服务端的实现(也即 ...

  3. Android组件体系之Service解析

    一.调用方式    1.启动服务    只启动一个服务,不进行通信,包括startService.startForegroundService两种调用方式.第二种方式适用于后台应用启动前台服务,在启动 ...

  4. Android组件体系之Activity启动模式解析

    本文主要分析Activity的启动模式及使用场景. 一.Activity启动模式浅析 1.standard 标准模式,系统默认的启动模式.在启动Activity时,系统总是创建一个新的Activity ...

  5. Android View体系(一)视图坐标系

    前言 Android View体系是界面编程的核心,他的重要性不亚于Android四大组件,在这个系列中我会陆续讲到View坐标系.View的滑动.View的事件分发等文章来逐步介绍Android V ...

  6. Android视图绘制流程完全解析,带你一步步深入了解View(二)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/16330267 在上一篇文章中,我带着大家一起剖析了一下LayoutInflater ...

  7. 2015最流行的Android组件、工具、框架大全

    Android 是目前最流行的移动操作系统之一. 随着新版本的不断发布, Android的功能也日益强大, 涌现了很多流行的应用程序, 也催生了一大批的优秀的组件. 本文试图将目前流行的组件收集起来以 ...

  8. 最流行的android组件大全

    目录 [−] 工具和教程 UI组件 类库 游戏引擎 Android HTML5应用 Android 是目前最流行的移动操作系统(还需要加之一吗?). 随着新版本的不断发布, Android的功能也日益 ...

  9. Android View体系(八)从源代码解析View的layout和draw流程

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

随机推荐

  1. HTML5的一些验证挺方便的

    一些基本的验证都可以很简单的实现,节省了很多繁琐的步骤.

  2. MySQL 库、表、记录、相关操作(2)

    库.表.记录.相关操作(2) 字段操作 create table tf1( id int primary key auto_increment, x int, y int ); # 修改 alter ...

  3. 配置防盗链、访问控制Directory和FilesMatch

    5月31日任务 课程内容: 11.25 配置防盗链11.26 访问控制Directory11.27 访问控制FilesMatch扩展几种限制ip的方法 http://ask.apelearn.com/ ...

  4. 阿里巴巴主导的“华山版《Java 开发手册》”简介

    1."83行代码计划"项目介绍(转自github): 2018年9月22日,在2018杭州云栖大会上,召开<码出高效:Java 开发手册>新书发布会,并宣布将图书所有收 ...

  5. Spring Cloud第六篇 | Hystrix仪表盘监控Hystrix Dashboard

    本文是Spring Cloud专栏的第六篇文章,了解前五篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Cloud ...

  6. es6 babel 安装以及使用

    1,安装好node(需要使用npm包管理工具) 2,在本地项目路径下npm init,格式化成功后会在项目下生成一个配置文件package.json 3,本地安装bable npm install - ...

  7. mac 安装 XX-Net-3.12.11

    目录 一 下载xx-net稳定版 二 使用Chrome浏览器 三 开启IPv6 mac禁用SIP机制 SIP 步骤 其他 附完整的csrutil命令 一 下载xx-net稳定版 github稳定版-X ...

  8. 2018 ACM/ICPC 南京 I题 Magic Potion

    题解:最大流板题:增加两个源点,一个汇点.第一个源点到第二个源点连边,权为K,然后第一个源点再连其他点(英雄点)边权各为1,然后英雄和怪物之间按照所给连边(边权为1). 每个怪物连终点,边权为1: 参 ...

  9. ASP.NET Core 选项模式源码学习Options IOptionsMonitor(三)

    前言 IOptionsMonitor 是一种单一示例服务,可随时检索当前选项值,这在单一实例依赖项中尤其有用.IOptionsMonitor用于检索选项并管理TOption实例的选项通知, IOpti ...

  10. 使用iCamera 测试AR0331 300w高分辨率摄像头小结

    使用iCamera 测试AR0331 300w高分辨率摄像头小结 先看下sensor特性 分辨率最高可达:2048*1536=300w像素 1080p帧率最高可达60fps 本次使用usb2,帧率14 ...