自定义View没有调用onDraw

自定义View没有调用onDraw

  我们在自定义View的时候有时会发现,重写的onDraw没有生被调用?这是为什么呢?大概率是因为你的自定义View继承自ViewGroup或者其子类,并只重写了onDraw方法。
  原因是ViewGoup以及子类默认关闭自动渲染,onDraw()方法不会被调用;View默认开启主动渲染, onDraw()会主动调用一次。针对ViewGroup自定义view不会被调用的情况,如下三种解决方法。

  • 1:自定义view在初始化时设置setWillNotDraw(false)
  • 2:自定义view在初始化的时候设置背景颜色(backgroud)
  • 3:自定义view在初始化的时候设置前景色(foreground)

  先看一下View的源码setWillNotDraw,

    /**
     * If this view doesn't do any drawing on its own, set this flag to
     * allow further optimizations. By default, this flag is not set on
     * View, but could be set on some View subclasses such as ViewGroup.
     *
     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
     * you should clear this flag.
     *
     * @param willNotDraw whether or not this View draw on its own
     */
    public void setWillNotDraw(boolean willNotDraw) {
        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
    }

  上面的解释就是如果布局本身不需要自己动手绘制,你就可以把willNotDraw设置为true。默认情况下View的willNotDraw是false,因为View一般需要绘制自己(onDraw),但是一些View的子类如ViewGroup,默认设置willNotDraw是true(因为一般ViewGroup的绘制都交给了子View去绘制)。所以你要是重写onDraw的话,一定会要清除willNotDraw这个flag,设置其为false。
  至于为什么设置背景(background)和设置前景(foreground)也能调用onDraw呢?通过查看View的源码,我们可以看到,View中有一个标志为PFLAG_SKIP_DRAW

    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
        dispatchDraw(canvas);
        ...
    } else {
        draw(canvas);
    }

这个flag控制着绘制的流程是dispatchDraw还是draw(draw函数内部会调用onDraw方法),而PFLAG_SKIP_DRAW则是由willNotDraw以及View的背景、前景决定的,

if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
        mPrivateFlags |= PFLAG_SKIP_DRAW;
    }

只有当View的背景和前景都为null,并且willNotDraw是true的情况下,PFLAG_SKIP_DRAW才被设置,这个时候就不会走draw流程,自然不会调用onDraw。但是有伙伴可能会问咯,这个时候会走dispatchDraw啊,没错,这个时候如果你需要进行绘制,就需要重写dispatchDraw进行操作了。

总结一下

  如果自定义View继承自ViewGroup或者它的子类,如果想进行绘制,总共有两种方法可供选择:

  • 1 重写onDraw。然后设置setWillNotDraw(false),或者给View设置背景或者前景。
  • 2 直接重写dispatchDraw,不需要其他操作了。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值