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_widthor 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);
}
Надеюсь, это поможет.