Android 自定义控件注意事项

1.为什么继承ViewGroup,draw(canvas: Canvas?)会不被调用?

在View中判断需要刷新控件的updateDisplayListIfDirty()方法中

public RenderNode updateDisplayListIfDirty() {
...
// Fast path for layouts with no backgrounds
  if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
      dispatchDraw(canvas);
      drawAutofilledHighlight(canvas);
      if (mOverlay != null && !mOverlay.isEmpty()) {
          mOverlay.getOverlayView().draw(canvas);
      }
      if (debugDraw()) {
          debugDrawFocus(canvas);
      }
    } else {
      draw(canvas);
    }
...
}

当(mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW会直接跳过当前控件的draw(canvas)方法。
而mPrivateFlags会在setBackgroundDrawable(Drawable background),setForeground(Drawable foreground),setDefaultFocusHighlight(Drawable highlight),setFlags(int flags, int mask)这四个方法中被设置成PFLAG_SKIP_DRAW。

public void setBackgroundDrawable(Drawable background) {
    ...
    if (background != null) {
        ...
    } else {
        /* Remove the background */
        mBackground = null;
        if ((mViewFlags & WILL_NOT_DRAW) != 0
                && (mDefaultFocusHighlight == null)
                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
            mPrivateFlags |= PFLAG_SKIP_DRAW;
        }
        ...
    }
  ..
}
public void setForeground(Drawable foreground) {
 ...
    if (foreground != null) {
       ...
    } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
            && (mDefaultFocusHighlight == null)) {
        mPrivateFlags |= PFLAG_SKIP_DRAW;
    }
   ...
}
private void setDefaultFocusHighlight(Drawable highlight) {
   ...
    if (highlight != null) {
      ...
    } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
            && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
        mPrivateFlags |= PFLAG_SKIP_DRAW;
    }
   ...
}

除了修改背景和前景以外,还可以用setFlags(int flags, int mask)方法来修改,而View里面有一个已经写好的方法setWillNotDraw(boolean willNotDraw),只要调用这个方法设置为false,那么ViewGroup的draw(canvas: Canvas?)方法就会被调用。

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

2.系统能处理的最短滑动距离ViewConfiguration.get().scaledTouchSlop

你可能感兴趣的:(Android 自定义控件注意事项)