我试图做自定义组件。我扩展View了课程并在onDraw覆盖的方法中进行了一些绘图。为什么我需要覆盖onMeasure?如果我没有,一切看起来都是正确的。有人可以解释一下吗?我应该如何编写我的onMeasure方法?我看过几个教程,但每个教程都有点不同。有时他们super.onMeasure在最后调用,有时他们使用setMeasuredDimension而不调用它。区别在哪里?
View
onDraw
onMeasure
super.onMeasure
setMeasuredDimension
毕竟我想使用几个完全相同的组件。我将这些组件添加到我的XML文件中,但我不知道它们应该有多大。我想稍后在自定义组件类中设置它的位置和大小(为什么我需要onMeasure在onDraw我绘制它时设置大小,也可以工作)。我到底什么时候需要这样做?
XML
onMeasure()您是否有机会告诉 Android 您希望自定义视图依赖于父级提供的布局约束有多大?这也是您的自定义视图有机会了解这些布局约束是什么(如果您希望在某种情况下表现得与某种match_parent情况不同wrap_content)。这些约束被打包到MeasureSpec传递给方法的值中。以下是众数值的粗略相关性:
onMeasure()
match_parent
wrap_content
MeasureSpec
layout_width
layout_height
存在的合同onMeasure()是setMeasuredDimension() 必须 在最后以您希望视图的大小调用。所有框架实现都会调用此方法,包括在 中找到的默认实现View,这就是为什么super如果适合您的用例,则可以安全地调用此方法。
setMeasuredDimension()
super
当然,因为框架确实应用了默认实现,所以您可能没有必要重写此方法,但是如果您不这样做,并且如果您布置了您的两个方向的自定义视图wrap_content,您的视图可能根本不会显示,因为框架不知道它有多大!
通常,如果您正在覆盖View而不是另一个现有的小部件,那么提供一个实现可能是一个好主意,即使它像这样简单:
@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); }
希望有帮助。