onMeasure()
это ваша возможность сообщить Android, насколько вы хотите, чтобы ваш пользовательский вид зависел от ограничений макета, предоставляемых родителем; это также возможность вашего пользовательского представления узнать, каковы эти ограничения макета (в случае, если вы хотите вести себя иначе в match_parent
ситуации, чем в wrap_content
ситуации). Эти ограничения упакованы в MeasureSpec
значения, которые передаются в метод. Вот грубая корреляция значений режима:
- Точно означает, что значение
layout_width
или layout_height
было установлено на конкретное значение. Вы должны, вероятно, сделать ваш вид этого размера. Это также может быть вызвано при match_parent
использовании, чтобы точно установить размер для родительского представления (это зависит от компоновки в платформе).
- AT_MOST обычно означает, что значение
layout_width
или layout_height
было установлено в match_parent
илиwrap_content
где требуется максимальный размер (это зависит от компоновки в платформе), а размер родительского измерения является значением. Вы не должны быть больше этого размера.
- UNSPECIFIED обычно означает, что значение
layout_width
or layout_height
было установлено wrap_content
без ограничений. Вы можете быть любого размера, который вам нравится. Некоторые макеты также используют этот обратный вызов, чтобы определить желаемый размер, прежде чем определять, какие спецификации фактически передают вас снова во втором запросе измерения.
Контракт, который существует, onMeasure()
заключается в том, что он setMeasuredDimension()
ДОЛЖЕН вызываться в конце с тем размером, который вы хотели бы видеть. Этот метод вызывается всеми реализациями фреймворка, в том числе реализацией по умолчанию View
, поэтому 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);
}
Надеюсь, это поможет.