onMeasure自定义视图说明

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

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


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

  • 完全意味着layout_widthlayout_height值被设置为特定值。 你可能应该让你的观点大小。 这也可以在使用match_parent时触发,以精确设置父视图的大小(这是依赖于框架的布局)。
  • AT_MOST通常意味着layout_widthlayout_height值被设置为match_parentwrap_content ,其中需要最大大小(这取决于框架中的布局),并且父维度的大小就是该值。 你不应该大于这个尺寸。
  • UNSPECIFIED通常表示layout_widthlayout_height值设定为wrap_content没有任何限制。 你可以是任何你想要的大小。 某些布局还会使用此回调来确定您希望的尺寸,然后再决定在第二个度量请求中实际再次传递给您的参数。
  • onMeasure()存在的契约是, 必须在最后调用setMeasuredDimension() ,并且您希望视图的大小。 这个方法被所有的框架实现调用,包括在View找到的默认实现,这就是为什么调用super而不是如果这符合你的用例是安全的。

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

    一般来说,如果你重写View而不是另一个已经存在的Widget,那么提供一个实现可能是一个好主意,即使它像这样简单:

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

    希望有所帮助。


    实际上,您的答案并不完整,因为这些值也取决于包装容器。 在相对或线性布局的情况下,值的行为如下所示:

  • 完全 match_parent是父母的完全+大小
  • AT_MOST wrap_content产生一个AT_MOST MeasureSpec
  • UNSPECIFIED从未触发
  • 在水平滚动视图的情况下,你的代码将工作。

    链接地址: http://www.djcxy.com/p/42623.html

    上一篇: onMeasure custom view explanation

    下一篇: how is the database created?