在我们自定义一个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;
}
}