gpt4 book ai didi

android - onMeasure() : wrap_content, 我怎么知道要换行的尺寸?

转载 作者:可可西里 更新时间:2023-11-01 18:59:08 24 4
gpt4 key购买 nike

我制作了一个覆盖了 onDraw() 的自定义 View ,它在 Canvas 上绘制位图。当我在布局文件中指定我想要 wrap_content 时,它仍然会填满整个屏幕。 onMeasure() 是这样说的:

The base class implementation of measure defaults to the background size, unless a larger size is allowed by the MeasureSpec. Subclasses should override onMeasure(int, int) to provide better measurements of their content.

好的,所以我知道我需要覆盖 onMeasure() 并使用 MeasureSpec。根据this answer

UNSPECIFIED means the layout_width or layout_height value was set to wrap_content. You can be whatever size you would like.

现在我的问题来了,如何在 onMeasure() 测量尚未创建的位图并测量/包装它?我知道其他 Android View 必须做一些事情,因为如果设置为 wrap_content,它们不会挡住整个屏幕。提前致谢!

最佳答案

This is the order这些常用的 View 方法运行于:

1. Constructor    // choose your desired size 
2. onMeasure // parent will determine if your desired size is acceptable
3. onSizeChanged
4. onLayout
5. onDraw // draw your view content at the size specified by the parent

选择所需尺寸

如果您的 View 可以是它想要的任何尺寸,它会选择什么尺寸?这将是您的 wrap_content 大小,并且取决于您的自定义 View 的内容。示例:

  • 如果您的自定义 View 是图像,那么您想要的尺寸可能是位图的像素尺寸加上任何填充。 (在选择大小和绘制内容时,您有责任将填充计算在内。)
  • 如果您的自定义 View 是一个模拟时钟,那么所需的尺寸可能是它看起来不错的一些默认尺寸。 (您始终可以获得设备的 dp to px size。)

如果您想要的尺寸需要大量计算,那么请在您的构造函数中进行计算。否则,您可以在 onMeasure 中分配它。 (onMeasureonLayoutonDraw 可能会被多次调用,所以这里不宜做繁重的工作。)

协商最终规模

onMeasure 是 child 告诉 parent 它想要多大的地方, parent 决定是否可以接受。这个方法经常被调用几次,每次都传入不同的尺寸要求,看能否达成一些妥协。不过,最终, child 需要尊重 parent 的尺寸要求。

我总是回到this answer当我需要复习如何设置我的 onMeasure 时:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int desiredWidth = 100;
int desiredHeight = 100;

int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);

int width;
int height;

//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}

//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}

//MUST CALL THIS
setMeasuredDimension(width, height);
}

在上面的示例中,所需的宽度和高度只是设置为一些默认值。您可以预先计算它们并使用类成员变量在此处设置它们。

使用选择的尺寸

onMeasure 之后,您的 View 的大小是已知的。这个大小可能是也可能不是你所要求的,但它是你现在必须使用的。在 onDraw 中使用该大小在您的 View 上绘制内容。

注意事项

  • 任何时候您对 View 所做的更改会影响外观但不会影响大小,然后调用 invalidate()。这将导致再次调用 onDraw(但不是所有其他以前的方法)。
  • 任何时候您对 View 进行的更改都会影响大小,然后调用 requestLayout()。这将从 onMeasure 重新开始测量和绘图的过程。通常是 combined with a call to invalidate() .
  • 如果出于某种原因您确实无法事先确定合适的所需尺寸,那么我想您可以按照@nmw 的建议进行操作,只要求零宽度、零高度。然后在加载所有内容后请求布局(不仅仅是 invalidate())。但这似乎有点浪费,因为您需要将整个 View 层次结构连续布置两次。

关于android - onMeasure() : wrap_content, 我怎么知道要换行的尺寸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13273838/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com