MeasureSpec returns 0 值 - onMeasure()

MeasureSpec returns a 0 value - onMeasure()

我已经搜索过这方面的答案,但没有找到解决方案。所以我在这里请求帮助。我正在创建自定义视图。我已经覆盖了 onMeasure。下面给出代码。

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int widthSize,heightSize;

    int measureWidthSpec = MeasureSpec.getMode(widthMeasureSpec);

    int measureHeightSpec = MeasureSpec.getMode(heightMeasureSpec);

    widthSize = getCircleWidth(measureWidthSpec, MeasureSpec.getSize(widthMeasureSpec));
    heightSize = getCircleHeight(measureHeightSpec,MeasureSpec.getSize(heightMeasureSpec));

    int circleSize = Math.min(widthSize,heightSize);

    setMeasuredDimension(circleSize, circleSize);

    Log.d(TAG, "View Measured and ViewDimension : " + heightSize + " " + MeasureSpec.getSize(widthMeasureSpec));
}

在此处使用 MeasureSpec.getSize(widthMeasureSpec) 请求尺寸时,返回 0。但是对于高度,我得到的值为 67。getCircleWidth() 和 getCircleHeight 是用于根据 specMode 固定值的方法。下面是我声明视图的布局 xml 文件部分。

 <com.example.raaja.circleview.CircleView
    android:id="@+id/CircleView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignBottom="@+id/textView"
    android:layout_toRightOf="@+id/textView"
    circle:circleColor="#5dade2"
    circle:innerCircleColor="#2874a6"
    circle:numberTextColor="#b3b6b7"
    />

谁能帮我看看为什么会返回值 0。也不会调用 onDraw,因为我在 setMeasuredDimension() 中修复了一个最小值。

你没有在 onMeasure() 中解释你到底想做什么,但假设你只是想让视图变成正方形,你可以简单地这样做:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int circleSize = Math.min(getMeasuredWidth(), getMeasuredHeight());
    setMeasuredDimension(circleSize, circleSize);
}

我从BladeCoder的回复中找到了这个解决方案的答案。问题实际上出在 Layout.xml。我已经用另一个按钮并排定义了视图。 Button 占据了所有宽度 space。所以这就是问题所在。如果您的观点未在下方绘制,则为 2 点解决方案。

  1. 检查 MeasureSpec.getsize()。如果它 returns 0 那么布局就没有 space 可以放置视图(宽度或高度),修复你的 layout.xml。如果不是,则继续检查您为修复 setMeasuredDimension() 上的尺寸所做的计算。这两个问题将是第二点的原因。

  2. 如果你在setMeasuredDimension()上传递0,onDraw()将不会被绘制。您可以传递 1000 或更大宽度但如果传递 0 高度(如 setMeasureDimension(1000,0))的原因,视图将不可见,因为它的高度为零。

希望这个回答能帮助您找到解决上述问题的方法。

在您可以使用传递给 onMeasure(int,int) 的测量值之前,您需要了解此参数的含义。

官方文档如下:

If you need finer control over your view's layout parameters, implement onMeasure(). This method's parameters are View.MeasureSpec values that tell you how big your view's parent wants your view to be, and whether that size is a hard maximum or just a suggestion. As an optimization, these values are stored as packed integers, and you use the static methods of View.MeasureSpec to unpack the information stored in each integer. Handle Layout Events

这一段告诉我们两件事:

  1. WidthMeasureSpec 和 WeightMeasureSpec 不是像素测量值。要获得实际像素值,请使用 MeasureSpec.getSize()

    int width = MeasureSpec.getSize(widthMeasureSpec)

  2. WidthMeasureSpec 和 WeightMeasureSpec 是建议值或要使用的最大值。要知道哪个是哪个,您可以使用 MeasureSpec.getMode()

    int mode = MeasureSpec.getMode(widthMeasureSpec);

    然后你可以像这样测试定义的常量(MeasureSpec.UNSPECIFIED,MeasureSpec.AT_MOST,MeasureSpec.EXACTLY)(注意你必须对宽度和高度都这样做):

    switch (mode) { case MeasureSpec.UNSPECIFIED: //no restriction we can set any width break; case MeasureSpec.AT_MOST: //we have to set a value that's less or equal //to MeasureSpec.getSize(widthMeasureSpec) break; case MeasureSpec.EXACTLY: //we have to use suggested measurement //use MeasureSpec.getSize(widthMeasureSpec); break; }

    始终确保您设置的测量值等于或高于 getSuggestedMinimumHeight() 和 getSuggestedMinimumWidth()。

考虑到这一点,我们现在可以回答您的问题了。当你的 width/height MeasuredSpec 为 0 时,你必须检查模式(记住这告诉你测量的含义)。 MeasureSpec.AT_MOST 或 MeasureSpec.EXACTLY 的值为 0 表示视图的布局中没有 space,因此您必须修改布局并为视图保留一些 space .现在当你得到 0 并且模式为 MeasureSpec.UNSPECIFIED 时,这意味着你可以将测量设置为任何你想要的,一个例子是当你有一个带有垂直 LinearLayoutManager 的 RecyclerView 时,你的高度并不重要设置是因为 RecyclerView 可以垂直滚动。

此致