您当前的位置: 首页 >  ar

韩曙亮

暂无认证

  • 1浏览

    0关注

    1068博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Android UI】Canvas 画布 ⑥ ( Canvas 绘图源码分析 | ViewRootImpl#draw 方法源码 | ViewRootImpl#drawSoftware 方法源码 )

韩曙亮 发布时间:2022-07-12 17:12:52 ,浏览量:1

文章目录
  • 一、Canvas 绘图源码分析
  • 二、ViewRootImpl#draw 方法源码
  • 三、ViewRootImpl#drawSoftware 方法源码

Canvas 状态保存机制 中 , 存在两个栈结构 , 分别是 状态栈 和 图层栈 ;

其中 图层栈 又称为 Layer 栈 ;

Canvas 画布中 , 有 2 2 2 套坐标系 , 分别是 :

  • Canvas 自身坐标系
  • Canvas 绘图坐标系
一、Canvas 绘图源码分析

参考 【Android 应用开发】UI绘制流程 ( 生命周期机制 | 布局加载机制 | UI 绘制流程 | 布局测量 | 布局摆放 | 组件绘制 | 瀑布流布局案例 ) 博客 , Android 的 UI 界面绘制流程为 :

  • 布局测量
  • 布局摆放
  • 组件绘制

这里 分析 Android 组件绘制过程中 , Canvas 画布相关操作 ;

在绘制时 , 最终调用的方法是 ViewRootImpl#draw 方法 , 在该方法中

Surface surface 是最终绘制的面板 ,

Surface surface = mSurface;

绘图时 , 首先要确认绘制区域 , 下面的代码就是 在 手机界面 中 定位出 绘制区域 用的 , 这块绘制区域 是属于 Surface 的 ,

        final Rect dirty = mDirty;
        if (mSurfaceHolder != null) {
            // The app owns the surface, we won't draw.
            dirty.setEmpty();
            if (animating && mScroller != null) {
                mScroller.abortAnimation();
            }
            return;
        }

        if (fullRedrawNeeded) {
            mAttachInfo.mIgnoreDirtyState = true;
            dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
        }

在该方法最后调用了 ViewRootImpl#drawSoftware 方法 , 进行下一步绘制操作 ;

                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
                    return;
                }

在 ViewRootImpl#drawSoftware 方法中 , 由 ViewRootImpl#mSurface 生成 Canvas 画布 , 并为 Canvas 设置绘制坐标 , Rect dirty 可以理解为 Canvas 的绘制坐标区域 ;

        // Draw with software renderer.
        final Canvas canvas;
        try {
            final int left = dirty.left;
            final int top = dirty.top;
            final int right = dirty.right;
            final int bottom = dirty.bottom;

            canvas = mSurface.lockCanvas(dirty);

            // The dirty rectangle can be modified by Surface.lockCanvas()
            //noinspection ConstantConditions
            if (left != dirty.left || top != dirty.top || right != dirty.right
                    || bottom != dirty.bottom) {
                attachInfo.mIgnoreDirtyState = true;
            }

            // TODO: Do this in native
            canvas.setDensity(mDensity);
        } 
二、ViewRootImpl#draw 方法源码

ViewRootImpl#draw 方法源码 :

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    private void draw(boolean fullRedrawNeeded) {
    	// 具体绘画的面板
        Surface surface = mSurface;
        if (!surface.isValid()) {
            return;
        }

        if (DEBUG_FPS) {
            trackFPS();
        }

        if (!sFirstDrawComplete) {
            synchronized (sFirstDrawHandlers) {
                sFirstDrawComplete = true;
                final int count = sFirstDrawHandlers.size();
                for (int i = 0; i            
关注
打赏
1663594092
查看更多评论
0.0475s