Android View的绘制流程

View的绘制

  • View的绘制流程主要经历3个阶段:测量、布局、绘制
    1. measure:判断是否需要重新计算View的大小
    2. layout:判断是否需要重新计算View的位置
    3. draw:判断是否需要重新绘制View
  • 对应的3个回调是,onMeasure、onLayout、onDraw

measure测量

  • MeasureSpec是一个32位的整数,由两部分组成,高2位是mode,低30位是size
  • mode有3个值{UNSPECIFIED, EXACTLY, AT_MOST},size就是测量模式下的尺寸
  • UNSPECIFIED:父View对子View没有任何约束,子View就是达到希望的最大尺寸
  • EXACTLY:(match_parent或具体的dp)父视图为子视图指定了一个确定的尺寸
  • AT_MOST:(wrap_content)父视图为子视图划定了一个最大尺寸,这个时候需要子View根据需求自己来计算自己大小,然后告诉父View
  • 在自定义View中重写onMeasure方法,可以获取到mode和seize,然后通过计算可以将修改后的值通过setMeasuredDimension方法传入
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        setMeasuredDimension(720,1280);
    }

layout摆放

  • 确定View在父布局中的摆放位置
  • 当View的位置发生变化时,会调用onLayout方法
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

draw绘制

  • 绘制自己
  • 通知子View去绘制(只有ViewGroup会dispatchDraw,View的dispatchDraw方法是空的)
 public void draw(Canvas canvas) {
 			...
            // Step 3, draw the content
            onDraw(canvas);
            // Step 4, draw the children
            dispatchDraw(canvas);
			...
}
  • 可以重写onDraw方法来自定义实现View的绘制内容
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        
    }

补充知识

在这里插入图片描述

  • 当Activity接收到焦点的时候就会被请求绘制UI布局,由FragmeWork层来完成。
  • Window窗口独占一个Surface实例
  • PhoneWindow是Window的唯一实现类
  • 用户界面通过PhoneWindow来承载
  • View是一个树的结构,它会从跟节点开始测量绘制,View树的绘制都是在代码ViewRootImpl中绘制的
  • 当建立起Decorview和ViewRoot的关联后,就会调用requestLayout方法请求首次绘制,在scheduleTraversals中通过来向Handler向主线程中发送消息,依次遍历来完成每次的绘制
	//首次布局
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    ...
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值