赞
踩
为了印证这个问题,我们写了一个自定义的View,继承自LInearLayout,没有设置background.
/** * ======================================================================================= * 作 者:caoxinyu * 创建日期:2020/7/21. * 类的作用: * 修订历史: * ======================================================================================= */ public class CustomLinearLayout extends LinearLayout { public CustomLinearLayout(Context context) { super(context); init(context); } private static final String TAG = "CustomLinearLayout"; public CustomLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); } public CustomLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Log.d(TAG, "t:" + t); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } @Override public void draw(Canvas canvas) { super.draw(canvas); int a = 300; } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); } }
代码跑起来,我们发现只会在dispatchDraw的断点停留,而其他两个方法断点都没有停留。
"main@10583" prio=5 tid=0x2 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at com.example.view.CustomLinearLayout.dispatchDraw(CustomLinearLayout.java:64)
at android.view.View.updateDisplayListIfDirty(View.java:20304)
at android.view.View.draw(View.java:21168)
at android.view.ViewGroup.drawChild(ViewGroup.java:4388)
at androidx.recyclerview.widget.RecyclerView.drawChild(RecyclerView.java:5030)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4149)
at android.view.View.draw(View.java:21439)
at androidx.recyclerview.widget.RecyclerView.draw(RecyclerView.java:4429)
因为我们的父容器是一个RecycleView,所以,我们只看从RecycleView调用过来的地方,我们发现他调用的是draw,但是有三个参数,和我们平时看到的只有一个参数canvas 的draw 方法有点不一样。
androidx.recyclerview.widget.RecyclerView#drawChild
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
return child.draw(canvas, this, drawingTime);
}
我们看下这个方法:
android.view.View#draw(android.graphics.Canvas, android.view.ViewGroup, long)
/** * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported) * @hide */ @NonNull 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); } } }
我们看到如果当前的View 的mPrivateFlags 有PFLAG_SKIP_DRAW flag,那么就不会调用draw,就自然不会调用onDraw, 只会调用dispatchDraw 方法。
我们可以看到自定义View的 mPrivateFlags 为 16812208 ,转换成十六进制就是0x10088b0.
static final int PFLAG_SKIP_DRAW = 0x00000080;
所以,我们的CustomLinearLayout是具备PFLAG_SKIP_DRAW这个属性的,所以只调用了dispatchDraw 而没有调用onDraw.
不一定会调用onDraw 和 draw 方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。