调整自定义视图的报告大小以包括绘制的图形

Posted

技术标签:

【中文标题】调整自定义视图的报告大小以包括绘制的图形【英文标题】:Adjust custom view's reported size to include drawn graphics 【发布时间】:2014-01-16 00:50:57 【问题描述】:

我有一个自定义视图类(称为FooView),我将其用作xml 布局的根元素。 FooView,在其onDraw()中,使用canvasFooView的底部边缘绘制一个形状。

我认为为了让FooView 不切断形状,我需要覆盖它的onMeasure 并做一些修改FooView 报告的高度,以便它现在包括绘制形状的高度.

正确吗?如果是这样,我需要做什么?

谢谢!

【问题讨论】:

【参考方案1】:

是的,如果您要创建自定义视图,则需要覆盖 onMeasure() 并提供您需要的大小。

因此,在onMeasure 的方法签名中,您将获得两个参数:

宽度测量规格 身高测量规格

您应该使用MeasureSpec 类来获得在调整视图大小时应该遵守的限制。

/*
 * This will be one of MeasureSpec.EXACTLY, MeasureSpec.AT_MOST, 
 * or MeasureSpec.UNSPECIFIED
 */
int mode = MeasureSpec.getMode(measureSpec);

//This will be a dimension in pixels
int pixelSize = MeasureSpec.getSize(measureSpec);

如果您得到MeasureSpec.EXACTLY,那么无论如何您都应该使用pixelSize 值作为您测量的宽度。

如果你得到MeasureSpec.AT_MOST,你应该确保你设置的测量宽度不大于pixelSize

如果您收到MeasureSpec.UNSPECIFIED,您可以根据需要占用尽可能多的空间。我通常只是将其解释为WRAP_CONTENT

所以你的onMeasure() 方法可能看起来像这样:

@Override
protected void onMeasure (int widthSpec, int heightSpec) 
    int wMode = MeasureSpec.getMode(widthSpec);
    int hMode = MeasureSpec.getMode(heightSpec);
    int wSize = MeasureSpec.getSize(widthSpec);
    int hSize = MeasureSpec.getSize(heightSpec);

    int measuredWidth = 0;
    int measuredHeight = 0;

    if (wMode == MeasureSpec.EXACTLY) 
        measuredWidth = wSize;
     else 
        //Calculate how many pixels width you need to draw your View properly
        measuredWidth = calculateDesiredWidth();

        if (wMode == MeasureSpec.AT_MOST) 
            measuredWidth = Math.min(measuredWidth, wSize);
        
    

    if (hMode == MeasureSpec.EXACTLY) 
        measuredHeight = hSize;
     else 
        //Calculate how many pixels height you need to draw your View properly
        measuredHeight = calculateDesiredHeight();

        if (hMode == MeasureSpec.AT_MOST) 
            measuredHeight = Math.min(measuredHeight, hSize);
        
    

    setMeasuredDimension(measuredWidth, measuredHeight);

【讨论】:

很好的回应!谢谢。只想补充一点,如果容器视图除了自定义图形之外还有子视图(例如,如果容器是LinearLayout 的子类),则在@987654336 中调用getMeasuredHeight()getMeasuredWidth() @(在调用 super.onMeasure(widthSpec, heightSpec) 之后)将为您提供容器所需的尺寸,其中仅包含子视图(不是自定义绘图)。更新容器的所需尺寸以包含自定义绘图,然后只需要添加这些尺寸并调用 setMeasuredDimension() 以获取结果。 不客气。 :) 如果它是已经处理测量的ViewGroup 的子类(例如您所说的LinearLayout),那是正确的,但是如果您只是将ViewGroup 子类化,则必须为您添加的任何子类实现测量和布局。 ViewGroup 上还有很多辅助方法,例如 measureChild()measureChildren()measureChildrenWithMargins() 和类似的东西,可以更轻松地根据 LayoutParams 测量所有子视图。

以上是关于调整自定义视图的报告大小以包括绘制的图形的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式调整自定义视图的大小?

自定义表格单元格未调整大小以适合内容视图

在自定义绘制的视图中动画大小变化的问题

在自定义容器控制器中旋转后视图未调整大小

使用窗口调整自定义视图的大小

Swift - 在标签中动态调整大小后动态调整视图大小