根据屏幕大小调整自定义视图的大小

时间:2012-05-20 00:14:29

标签: java android android-layout drawing

我一直在努力寻找解决方案,但也许我不理解“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中将这些视图彼此相邻放置时,第一个视图的大小正确(它确实是宽度的一半减去一点),但是第二个视图要小得多,可能只有一半大小最后一个视图的宽度减去多一点! (我会张贴一张照片,但不幸的是我没有足够的声誉这样做......)

应该出现的是两个框应该是相同的大小,无论我在哪里放置它们。它们都应该是屏幕宽度的一半,减去一点点。

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

4 个答案:

答案 0 :(得分: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()”来重绘视图。有些东西必须调用这个方法,所以我在活动中这样做。首先,我使用以下代码获取活动中屏幕的大小,而不是视图:

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);

现在,所有视图的大小都相同。我不知道这是否是最佳方式,但它现在有效,我想我会在这里发布,所以每个人都知道。 :)

答案 1 :(得分:1)

老问题..但是这里是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)
    );
}

答案 2 :(得分:0)

我认为您需要阅读onMeasure上的文档,并了解它是如何运作的。

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

当调用onMeasure时,您首先想要通过调用MeasureSpec.getMode(widthMeasureSpec)来查看您收到的MeasureSpec类型。这将返回MeasureSpec.AT_MOSTMeasureSpec.EXACTLY

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

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

然后你将这个数字除以2,第二个视图只有容器水平宽度的25%,而第一个视图得到水平宽度的50%。

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

编辑:再次重读您的问题,我认为您的问题是您假设widthMeasureSpec与屏幕宽度相同(它没有)。您可以尝试正确查询屏幕的宽度,并根据它调用setMeasureDimension,尽管它可能不适用于所有情况。如果您不小心,您可以根据测量请求宽度大于分配给您的宽度。或者有时你会被称为onMeasure MeasureSpec.EXACTLY,此时你别无选择,只能使用提供的宽度或高度。

答案 3 :(得分: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。