У меня есть расширенный RelativeLayout
, который, когда программно позиционируется и измеряется с использованием RelativeLayout.LayoutParams
, должен ограничивать себя заданным соотношением сторон. Как правило, я хотел бы, чтобы оно ограничивалось 1: 1, поэтому, если RelativeLayout.LayoutParams
содержит width
200 и height
100, пользовательский RelativeLayout
будет ограничиваться 100 x 100.
Я уже привык переопределять onMeasure()
в обычных пользовательских View
s для достижения аналогичных целей. Например, я создал свой собственный конвертер изображений SVG, а пользовательский View
, который отображает изображение SVG, имеет переопределенный onMeasure()
, который гарантирует, что вызов setMeasuredDimension()
содержит измерения, которые (a) соответствуют исходным спецификациям измерений и (b) соответствуют соотношению сторон исходного изображения SVG.
Возвращаясь к своему обычаю RelativeLayout
, который я хотел бы ограничить аналогичным образом, я попытался переопределить onMeasure()
, но у меня не было большого успеха. Зная, что RelativeLayout
onMeasure()
выполняет все дочерние View
размещения, то, что я обычно пытаюсь сделать в данный момент, но без желаемых результатов, это переопределить onMeasure()
таким образом, что я первоначально изменяю сначала укажите размерные характеристики (т.е. примените мои желаемые ограничения), а затем вызовите super.onMeasure()
. Как это:
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// Restrict the aspect ratio to 1:1, fitting within original specified dimensions
int chosenDimension = Math.min(chosenWidth, chosenHeight);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(chosenDimension, MeasureSpec.AT_MOST);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(chosenDimension, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Что на самом деле происходит, когда я это делаю, так это то, что, как ни странно, высота должным образом ограничена, как я и предполагал, а ширина - нет. Для иллюстрации:
Задание высоты 200 и ширины 100 в RelativeLayout.LayoutParams
приводит к тому, что мой пользовательский RelativeLayout
имеет высоту 100 и ширину 100. -> Правильно.
Задание высоты 100 и ширины 200 в RelativeLayout.LayoutParams
приводит к тому, что мой пользовательский RelativeLayout
имеет высоту 100 и ширину 200. -> Неправильно.
Я понимаю, что вместо этого я мог бы применить свою логику ограничения соотношения сторон в вызывающем классе, который ставит RelativeLayout
на первое место (и в то же время я вполне могу сделать это, чтобы обойти это), но на самом деле это детали реализации, которые я хочу, чтобы сам RelativeLayout
выполнил.
Уточнение: результирующие значения ширины и высоты, которые я читаю, взяты из использования getWidth()
и getHeight()
. Эти значения считываются в будущем, после того, как процесс макета был выполнен снова.