当前位置: 首页 > 知识库问答 >
问题:

onMeasure自定义视图解释

司空鸿熙
2023-03-14

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

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

共有3个答案

蒲坚
2023-03-14

如果你不需要在测量时更改某些内容,那么绝对没有必要覆盖它。

开发代码(此处选择和投票最多的答案)与SDK实现已经为您做的几乎相同(我检查了-它自2009年以来就这样做了)。

您可以在此处检查onMeasure方法:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
            getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}

public static int getDefaultSize(int size, int measureSpec) {
    int result = size;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    switch (specMode) {
    case MeasureSpec.UNSPECIFIED:
        result = size;
        break;
    case MeasureSpec.AT_MOST:
    case MeasureSpec.EXACTLY:
        result = specSize;
        break;
    }
    return result;
}

用完全相同的代码替换SDK代码毫无意义。

这篇官方文档声称“默认的onInstrure()将始终设置大小为100x100”是错误的。

楚博雅
2023-03-14

实际上,您的答案并不完整,因为值还取决于包装容器。对于相对或线性布局,值的行为如下:

  • 精确match_parent是父节点的精确大小
  • AT_MOSTwrap_content导致AT_MOST测量规格
  • 未指明从未触发

在水平滚动视图的情况下,您的代码将起作用。

和斌
2023-03-14

onMeasure()是你告诉Android你希望你的自定义视图有多大取决于家长提供的布局约束的机会;这也是您的自定义视图了解这些布局约束的机会(如果您希望在匹配父对象的情况下与包裹内容的情况下表现不同)。这些约束打包成传递给方法的measurepe值。以下是模式值的粗略相关性:

  • 精确表示布局宽度或布局高度值设置为特定值。您可能应该将视图设置为此大小。当使用match_parent(匹配父视图)将大小精确设置为父视图(这取决于框架中的布局)时,也会触发此操作
  • AT_最典型的意思是,在需要最大大小(这取决于框架中的布局)的情况下,将“布局宽度”或“布局高度”值设置为“匹配父项”或“包裹内容”,父维度的大小就是该值。你不应该比这个尺寸大
  • 未指定通常意味着无限制地将布局宽度或布局高度值设置为包装内容。你想穿什么尺码都行。一些布局还使用此回调来确定所需的大小,然后再确定在第二个测量请求中实际传递给您的规格

与onMeasure()存在的约定是,必须在最后以您希望的视图大小调用setMeasuredDimension()。此方法由所有框架实现调用,包括在视图中找到的默认实现,这就是为什么如果适合您的用例,则可以安全地调用super。

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

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

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

希望有帮助。

 类似资料:
  • 英文原文:http://emberjs.com/guides/views/customizing-a-views-element 视图在页面上表现为一个单一的DOM元素。通过修改tagName属性,可以改变视图生成的元素的类型。 1 2 3 App.MyView = Ember.View.extend({ tagName: 'span' }); 另外,还可以通过设置一个字符串数组到clas

  • 英文原文:http://emberjs.com/guides/views/defining-a-view/ 你可以使用Ember.View来渲染一个Handlebars模板并将它插入到DOM中。 为了告诉视图要用哪个模板,可以设置它的temaplateName属性。例如,如果我有一个像这样的<script>标签: 1 2 3 4 5 6 7 <html> <head> <script

  • 问题内容: 我有一个 : 问题答案: 首先应注意,通过简单地调整系统提供的标注的属性,但 自定义左右附件(通过rightCalloutAccessoryView和leftCalloutAccessoryView),就可以对标注进行最简单的更改。您可以在中进行配置viewForAnnotation。 从iOS 9开始,我们可以使用detailCalloutAccessoryViewwhich来用可能

  • 本文向大家介绍Android 创建自定义视图,包括了Android 创建自定义视图的使用技巧和注意事项,需要的朋友参考一下 示例 如果需要完全自定义的视图,则需要子类View(所有Android视图的超类),并提供自定义的sizing(onMeasure(...))和drawing(onDraw(...))方法: 创建您的自定义视图框架:每个自定义视图的基本相同。在这里,我们为自定义视图创建框架,

  • 主要内容:前记,1.自定义视图,2.自定义异常,3.自定义异常的原理前记 在前面的文章中, 表示了视图解析的原理和异常解析器的解析原理。 这篇通过如何自定义视图和自定义异常处理和自定义异常处理的原理进行说明。 这里说明一下, 自定义的视图和自定义的异常都是会代替容器默认的组件的, 异常还好说, 就是不符合就抛, 视图的话需要注意一下优先级, 可以在自定义的视图解析器上加上注解。 1.自定义视图 这里原理就是添加一个视图和视图解析器, 然后放入容器中, 最后访问相应

  • 我正在创建一个自定义的ImageView,它将我的图像裁剪成一个六边形形状,并添加一个边框。我想知道我的方法是正确的还是我的做法是错误的。有一堆自定义库已经这样做了,但没有一个开箱即用的形状,我正在寻找。话虽如此,这更多的是一个关于最佳实践的问题。 您可以在这个要点中看到完整的类,但主要问题是这是否是最好的方法。我觉得不对,部分原因是一些神奇的数字,这意味着它可能会在某些设备上搞砸。 下面是代码的