4

我一直在努力寻找解决方案,但也许我不明白“onMeasure()”方法在 Android 中的效果如何!

这是我第一次在 Android 中制作“动态”自定义视图,因此我了解到您需要覆盖“onMeasure()”方法才能根据屏幕大小调整视图大小。我希望我的视图是屏幕宽度的一半,再加上一点额外的(这个数字是任意的,只要它相对较小,在 3 到 5 之间),所以我为 onMeasure 方法编写了以下代码:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    int halfWidth = (MeasureSpec.getSize(widthMeasureSpec) / 2) - 5;

    this.setMeasuredDimension((int) halfWidth, (int) halfWidth);
}

我确信这是一种糟糕的处理方式,因为我在网上找到的所有代码都比我在尝试完成类似的事情时所做的要多得多!

当我在 XML 中将这些视图彼此相邻放置时,第一个视图的大小是正确的(它确实是宽度的一半减去一点点),但第二个视图要小得多,可能是宽度的一半最后一个视图减去更多!(我会发布一张照片,但不幸的是我没有足够的声誉来这样做......)

应该发生的是这两个框应该是相同的大小,无论我将它们放在 XML 中的什么位置。它们都应该是屏幕宽度的一半,减去一点额外的。

我知道这与我如何使用“setMeasuredDimension()”有关,但我不知道它是什么。我真的希望有人能为我澄清一下!谢谢!:)

4

4 回答 4

3

实际上,我今天通过基于蒂姆所说的一些实验完成了这一点。我离开了“onMeasure()”,只为它写了这段代码:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    // Call the super class.
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    // Set the dimensions of this view.
    this.setMeasuredDimension((int) width, (int) width);
}

宽度是一个全局浮点数。宽度从何而来?我从我在视图中编写的这个方法派生了宽度以调整大小:

public void initSize(float size)
{
    width = size;
    this.invalidate();
}

我调用“invalidate()”来重绘视图。不过有些东西必须调用这个方法,所以我在活动中这样做了。首先,我使用以下代码在 Activity 中获取屏幕大小,而不是在 View 中:

Display thisDisplay = this.getWindowManager().getDefaultDisplay();
Point desiredSize = new Point();
display.getSize(desiredSize);
int width = size.x;

您曾经可以在“thisDisplay”上调用名为“getWidth()”的方法,但该方法现在已弃用,因此您应该改用“getSize()”。最后,在初始化构造函数之后,立即调用“initSize()”方法:

nameBox = (InfoBoxView) findViewById(R.id.nameBox);
    nameBox.initSize(width);

现在,所有视图都将具有相同的大小。我不知道这是否是最好的方法,但它现在有效,我想我会把它贴在这里让每个人都知道。:)

于 2012-05-20T13:41:47.650 回答
2

老问题..但这里是 onMeasure ,它使视图呈方形并且小于屏幕的一半,而无需在 Activity 中编写任何额外的代码。您可以更改它以产生任何其他尺寸比。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // get view dimensions suggested by layout
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    // width should never be more than half of a screen
    int displayWidth = getContext().getResources().getDisplayMetrics().widthPixels;
    width = Math.min(width, displayWidth/2);
    // always make it a square (use the smaller dimension of the two)
    if (width > height) {
        width = height;
    } else {
        height = width;
    }
    // use the values
    super.onMeasure(
            MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
    );
}
于 2016-01-03T18:30:50.457 回答
0

我认为您需要阅读有关onMeasure的文档并了解它是如何工作的。

它实际上被多次调用,具体取决于视图所在的布局容器的类型,具体细节会因视图组而异。通常,第一次尺寸最松散,然后随着更多组件的布局变得更细粒度。

当 onMeasure 被调用时,你首先想通过调用来查看你收到了什么样的 MeasureSpec MeasureSpec.getMode(widthMeasureSpec)。这将返回MeasureSpec.AT_MOSTMeasureSpec.EXACTLY

如果它返回 AT_MOST,则表示此时视图可以填充的最大可能区域。当您布置第一个视图时,可能会说您的第一个视图最多可以使用屏幕的整个宽度,因为还没有布置其他组件。将容器的整个宽度除以 2,然后通过调用setMeasuredDimension.

接下来,当onMeasure为您的第二个视图调用时,现在只有容器水平宽度的一半可用,因为您已经为第一个视图请求了一半的屏幕。

然后将该数字除以 2,使第二个视图仅占容器水平宽度的 25%,而第一个视图占水平宽度的 50%。

我建议覆盖 onMeasure 不是让视图使用一半屏幕的正确方法,尽管我想解释它是如何工作的。您认为仅使用标准 xml 布局无法实现这一点有什么原因吗?

编辑:再次阅读您的问题,我认为您的问题是您假设 widthMeasureSpec 与屏幕宽度的含义相同(它不是)。您可以尝试正确查询屏幕的宽度并setMeasureDimension以此为基础进行调用,尽管它可能并非在每种情况下都有效。如果您不小心,您可能会要求宽度大于根据测量分配给您的宽度。或者有时你会被称为onMeasurewith MeasureSpec.EXACTLY,此时你别无选择,只能使用提供的宽度或高度。

于 2012-05-20T00:34:16.980 回答
0

我认为问题在于父视图的大小也已减小,根据您的说法,可能是大小的一半。因此我建议代码:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
   // Prevent reducing the size of the parent view
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);

   int halfWidth = (MeasureSpec.getSize(widthMeasureSpec) / 2) - 5;

   this.setMeasuredDimension((int) halfWidth, (int) halfWidth);
}

另外,您的 XML 布局是什么样的?这可能也需要修复,尽管怀疑这是问题所在。

我没有用我的 Android SDK 尝试这个。

于 2012-05-20T05:14:58.197 回答