onMeasure 自定义视图说明 [英] onMeasure custom view explanation

查看:29
本文介绍了onMeasure 自定义视图说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试做自定义组件.我扩展了 View 类并在 onDraw 覆盖的方法中做一些绘图.为什么我需要覆盖 onMeasure?如果我没有,一切都被认为是正确的.有人可以解释一下吗?我应该如何编写我的 onMeasure 方法?我看过几个教程,但每一个都与另一个略有不同.有时他们在最后调用 super.onMeasure ,有时他们使用 setMeasuredDimension 而没有调用它.区别在哪里?

I tried to do custom component. I extended View class and do some drawing in onDraw overrided method. Why I need to override onMeasure? If I didn't, everything seen to be right. May someone explain it? How should I write my onMeasure method? I've seen couple tutorials, but each one is a little bit different than the other. Sometimes they call super.onMeasure at the end, sometimes they use setMeasuredDimension and didn't call it. Where is a difference?

毕竟我想使用几个完全相同的组件.我将这些组件添加到我的 XML 文件中,但我不知道它们应该有多大.我想稍后在自定义组件类中设置它的位置和大小(为什么我需要在 onMeasure 中设置大小,如果在我绘制它时在 onDraw 中也能正常工作).我什么时候需要这样做?

After all I want to use several exactly the same components. I added those components to my XML file, but I don't know how big they should be. I want to set its position and size later (why I need to set size in onMeasure if in onDraw when I draw it, is working as well) in custom component class. When exactly I need to do that?

推荐答案

onMeasure() 是你告诉 Android 你希望自定义视图依赖父级提供的布局约束有多大的机会;这也是您的自定义视图有机会了解这些布局约束是什么(如果您希望在 match_parent 情况下与 wrap_content 情况下表现不同).这些约束被打包到传递到方法中的 MeasureSpec 值中.以下是模式值的粗略相关性:

onMeasure() is your opportunity to tell Android how big you want your custom view to be dependent the layout constraints provided by the parent; it is also your custom view's opportunity to learn what those layout constraints are (in case you want to behave differently in a match_parent situation than a wrap_content situation). These constraints are packaged up into the MeasureSpec values that are passed into the method. Here is a rough correlation of the mode values:

  • EXACTLY 表示 layout_widthlayout_height 值已设置为特定值.您可能应该将视图设置为这种大小.这也可以在使用 match_parent 时触发,以将大小精确设置为父视图(这取决于框架中的布局).
  • AT_MOST 通常表示 layout_widthlayout_height 值设置为 match_parentwrap_content 其中需要最大尺寸(这是框架中的布局相关),并且父维度的尺寸是值.您的尺寸不应大于此尺寸.
  • UNSPECIFIED 通常意味着 layout_widthlayout_height 值被设置为 wrap_content,没有任何限制.你可以是任何你想要的尺寸.某些布局还使用此回调来确定您想要的尺寸,然后再确定在第二个测量请求中实际再次传递给您的规格.
  • EXACTLY means the layout_width or layout_height value was set to a specific value. You should probably make your view this size. This can also get triggered when match_parent is used, to set the size exactly to the parent view (this is layout dependent in the framework).
  • AT_MOST typically means the layout_width or layout_height value was set to match_parent or wrap_content where a maximum size is needed (this is layout dependent in the framework), and the size of the parent dimension is the value. You should not be any larger than this size.
  • UNSPECIFIED typically means the layout_width or layout_height value was set to wrap_content with no restrictions. You can be whatever size you would like. Some layouts also use this callback to figure out your desired size before determine what specs to actually pass you again in a second measure request.

onMeasure() 存在的契约是 setMeasuredDimension() 必须 在最后以您想要的大小调用认为.此方法由所有框架实现调用,包括在 View 中找到的默认实现,这就是为什么在适合您的用例的情况下调用 super 是安全的.

The contract that exists with onMeasure() is that setMeasuredDimension() MUST be called at the end with the size you would like the view to be. This method is called by all the framework implementations, including the default implementation found in View, which is why it is safe to call super instead if that fits your use case.

当然,由于框架确实应用了默认实现,因此您可能不需要重写此方法,但是在视图空间小于您的内容的情况下,如果您不这样做,您可能会看到裁剪,并且如果您使用 wrap_content 在两个方向上布置您的自定义视图,您的视图可能根本不显示,因为框架不知道它有多大!

Granted, because the framework does apply a default implementation, it may not be necessary for you to override this method, but you may see clipping in cases where the view space is smaller than your content if you do not, and if you lay out your custom view with wrap_content in both directions, your view may not show up at all because the framework doesn't know how large it is!

通常,如果您要覆盖 View 而不是另一个现有的小部件,那么提供一个实现可能是个好主意,即使它像这样简单:

Generally, if you are overriding View and not another existing widget, it is probably a good idea to provide an implementation, even if it is as simple as something like this:

@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 自定义视图说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆