MeasureSpec返回0值 - onMeasure()

时间:2016-02-11 12:29:27

标签: android android-layout android-view

我搜索过有关此问题的答案,但尚未找到解决方法。所以我在这里请求帮助。我正在创建一个自定义视图。我已经超越了测量。代码见下文。

   @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()中修复了最小值。

3 个答案:

答案 0 :(得分:3)

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

  1. 检查MeasureSpec.getsize()。如果它返回0,则布局没有空间放置视图(宽度或高度),修复layout.xml。如果没有,则继续检查您在setMeasuredDimension()上修复维度的计算。这两个问题将成为第二点的原因。

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

  3. 我希望这个答案可以帮助您找到解决上述问题的方法。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

官方文档内容如下:

  

如果您需要更好地控制视图的布局参数,   实现onMeasure()。该方法的参数是View.MeasureSpec   告诉您视图的父级希望您的视图有多大的值,   以及该大小是硬性最大值还是仅是建议。作为一个   优化,这些值存储为压缩整数,您可以使用   View.MeasureSpec的静态方法来解压信息   存储在每个整数中。 Handle Layout Events

此段告诉我们2件事:

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

    int width = MeasureSpec.getSize(widthMeasureSpec)

  2. 建议使用
  3. 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表示视图的布局中没有空间,因此您必须修改布局并为视图保留一些空间。现在,当您获得0且模式为MeasureSpec.UNSPECIFIED时,这意味着您可以将测量值设置为所需的任何值,例如,当您具有带有垂直LinearLayoutManager的RecyclerView时,设置的高度无关紧要,因为RecyclerView可以垂直滚动。

致谢