Android 如果onMeasure()最多选择最小尺寸,则不会绘制自定义视图布局

Android 如果onMeasure()最多选择最小尺寸,则不会绘制自定义视图布局,android,android-linearlayout,android-custom-view,ondraw,Android,Android Linearlayout,Android Custom View,Ondraw,我的自定义视图是一个滑块,当选择视图高度时,它遵循onMeasure()的规则;当MeasureSpec精确地时,它设置规格大小;当未指定时,它设置使用定义的大小;当最多时,它选择两者之间的最小值 int heightMode = MeasureSpec.getMode(heightMeasureSpec); int specHeight = Math.max(BOX_MIN_HEIGHT, MeasureSpec.getSize(heightMeasureSpe

我的自定义视图是一个滑块,当选择视图高度时,它遵循
onMeasure()
的规则;当
MeasureSpec
精确地时,它设置规格大小;当未指定时,它设置使用定义的大小;当最多时,它选择两者之间的最小值

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int specHeight = Math.max(BOX_MIN_HEIGHT, MeasureSpec.getSize(heightMeasureSpec));
        int specWidth = MeasureSpec.getSize(widthMeasureSpec);

        int desiredHeight = Math.max(BOX_MIN_HEIGHT, HSVColorPickerPreference.this.boxHeight);

        int chosenHeight = 0;

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if( heightMode == MeasureSpec.UNSPECIFIED ) {
            chosenHeight = desiredHeight;
        } else if( heightMode == MeasureSpec.AT_MOST ) {
            chosenHeight = Math.min(specHeight, desiredHeight); <<< BAD results
            //chosenHeight = specHeight; <<< GOOD results
        } else if( heightMode == MeasureSpec.EXACTLY ) {
            chosenHeight = specHeight;
        }

        setMeasuredDimension(specWidth, chosenHeight);
错误日志(没有调用
onDraw()
):


因为我终于明白了发生了什么,所以我在这里留下了答案供将来参考:

Android正在做它在测量UI组件时必须做的事情。
如果用户(在本例中为me)不遵循简单规则,则可能恰好发生0。
如果您只需在
onSizeChanged()
方法中检查大小是否为0,则可以使其无害。但如果你像我一样避免混合度量模式,那就更好了。解释如下

我在XML加权视图中定义(使用
layout\u weight
)。这些是问题中提到的习惯观点。我的错误是,我还试图为视图要求一个特定的高度

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
罪魁祸首是那些线

int desiredHeight = Math.max(BOX_MIN_HEIGHT, HSVColorPickerPreference.this.boxHeight);

. . . 

    chosenHeight = Math.min(specHeight, desiredHeight);

. . .
这与加权布局的启发式方法正面冲突。为什么?让我们以3个权重为1的小部件为例,其中一个表现不好,如上所述

当LineralLayout第一次超过它的孩子时,它会让他们变得狂野,并要求他们想要的任何尺寸。在我们的示例2中,小部件将要求尽可能多的内容,而定制小部件将要求一些适度的内容,低于最大值

第二个关卡是杀手级的,LinearLayout不知道其中一个加权小部件的价格比预期的要低,总之,它定义了一个权重。LinearLayout查看请求的度量值表单pass one的总数,发现它超出了必须给出的范围。然后,它计算增量溢出,并在加权小部件之间进行另一次传递以分配溢出。 因此,自定义视图小部件必须缩减超出其请求的部分,使其保持0大小

这种情况类似于和朋友去喝啤酒。你点了一杯啤酒,你的朋友点了啤酒、薯条、猎犬等等。晚上结束时,支票在每个人中间平分,你最后支付的钱比你喝的啤酒还多。我的自定义视图也是如此

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
int desiredHeight = Math.max(BOX_MIN_HEIGHT, HSVColorPickerPreference.this.boxHeight);

. . . 

    chosenHeight = Math.min(specHeight, desiredHeight);

. . .