自定义ViewGroup ondraw方法不被调用解决办法

在我们自定义一个View, 继承自ViewGrop, 或其他某些ViewGroup的子类时, 若我们要在ViewGroup中进行一些绘制,我们会想到重写父类的ondraw, 但我们发现此时ondraw并没有被调用,达不到我们想要的效果。我此前的解决办法是重写draw, 解决了我的问题(不知到是否有其他的副作用)。之后我又发现了两种可以使ondraw被调用的方法。

方法一:在构造函数中调用setWillNotDraw(false);
方法二:给ViewGroup设置背景。调用setBackground。

ondraw不调用的原因:ViewGroup作为一个容器控件,默认情况下是没有任何东西可画的,它是一个透明控件。draw被调用而ondraw不被调用,而ondraw是由draw进行调用的,代码如下:

    if (!dirtyOpaque) onDraw(canvas);

说明此时dirtyOpaque为true,而

final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);

方法一和方法二都会改变privateFlags达到调用ondraw的目的。

setWillNotDraw在View中,源码如下:

    /**
     * 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);
    }

setBackground在View中,源码如下:

    public void setBackground(Drawable background) {
        //noinspection deprecation
        setBackgroundDrawable(background);
    }

直接调用setBackgroundDrawable:

   /**
     * @deprecated use {@link #setBackground(Drawable)} instead
     */
    @Deprecated
    public void setBackgroundDrawable(Drawable background) {
        computeOpaqueFlags();

        if (background == mBackground) {
            return;
        }

       ...
    }

调用computeOpaqueFlags();

     * @hide
     */
    protected void computeOpaqueFlags() {
        // Opaque if:
        //   - Has a background
        //   - Background is opaque
        //   - Doesn't have scrollbars or scrollbars overlay

        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
        } else {
            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
        }

        final int flags = mViewFlags;
        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
        } else {
            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
        }
    }

猜你喜欢

转载自blog.csdn.net/castle_cc/article/details/52153602