繁体   English   中英

onMeasure():wrap_content,我怎么知道要包装的大小?

[英]onMeasure(): wrap_content, how do I know the size to wrap?

我已经使用onDraw()覆盖了自定义视图,在画布上绘制了一个位图。 当我在布局文件中指定我想要它wrap_content时,它仍然会填满整个屏幕。 onMeasure()说:

measure的基类实现默认为背景大小,除非MeasureSpec允许更大的大小。 子类应覆盖onMeasure(int,int)以提供更好的内容测量。

好的,所以我知道我需要覆盖onMeasure()并使用MeasureSpec 根据这个答案

unex表示layout_width或layout_height值设置为wrap_content。 你可以任意大小。

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

这是运行这些常用视图方法的顺序

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

选择所需的尺寸

如果你的视图可以是它想要的任何尺寸,它会选择多大的尺寸? 这将是您的wrap_content大小,将取决于您的自定义视图的内容。 例子:

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

如果您想要的大小使用繁重的计算,那么在构造函数中执行此操作。 否则,你可以在onMeasure分配它。 onMeasureonLayoutonDraw可能会被多次调用,这就是为什么在这里做繁重工作不好的原因。)

谈判最终规模

onMeasure是孩子告诉父母有多大的地方,父母决定这是否可以接受。 这种方法经常被调用几次,每次都传递不同的大小要求,看看是否可以达到一些妥协。 但最后,孩子需要尊重父母的身材要求。

当我需要复习如何设置我的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之后,您的视图大小已知。 这个大小可能是您要求的,也可能不是您所要求的,但这是您现在必须使用的。 使用该大小在onDraw上绘制视图上的内容。

笔记

  • 每当您对视图进行更改而影响外观但不影响大小时,请调用invalidate() 这将导致再次调用onDraw (但不是所有其他先前的方法)。
  • 如果您对视图进行了更改会影响大小,请调用requestLayout() 这将从onMeasure开始重新测量和绘制的过程。 它通常与对invalidate()的调用相结合
  • 如果由于某种原因你事先无法确定合适的所需尺寸,那么我想你可以像@nmw建议那样做,只要求零宽度,零高度。 然后在加载所有内容后请求布局(不只是invalidate() )。 这看起来有点浪费,因为您要求整个视图层次结构连续布局两次。

如果在onMeasure调用之前无法测量位图,则可以返回大小为零,直到加载位图。 加载后,使父ViewGroup无效以强制执行另一个度量(不记得View本身上的invalidate()是否会强制onMeasure)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM