Intereting Posts
Как использовать задачуCheckCheck для запуска тестов на удаленных устройствах Настройка переменной окружения ANDROID_HOME в Mac OS X FileObserver не работает на внешнем хранилище в Android 6.0 Marshmallow (API 23) Как интегрировать кнопку плавающего действия в линейную компоновку с панелью инструментов Base.Widget.AppCompat.Button vs Widget.AppCompat.Button Ошибка сброса соединения студии Android? Проверьте, включен ли доступ к моему местоположению – Android Скрыть / отключить меню по умолчанию в пользовательской закладке Chrome Как я могу узнать язык клавиатуры? (о / FR) Как предоставить разрешение на использование adb без укорачивания устройств Новая активность в Android «введите со стороны» Выпадающее заклинание вне панели действий? (IceCream Sandwich style, w / ActionBarSherlock) Длительное нажатие кнопки GestureDetector также срабатывает при нажатии Есть ли недостаток в использовании только изображений с высоким разрешением для приложений Android? Как передать возвращаемые значения из функции javascript в android?

Уверенный способ переопределить onMeasure ()?

Каков правильный способ переопределения onMeasure ()? Я видел различные подходы. Например, Professional Android Development использует MeasureSpec для вычисления размеров, а затем заканчивается вызовом setMeasuredDimension (). Например:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); this.setMeasuredDimension(parentWidth/2, parentHeight); } 

С другой стороны, согласно этому сообщению , «правильный» способ – использовать MeasureSpec, вызвать setMeasuredDimensions (), а затем вызвать setLayoutParams () и завершить вызов super.onMeasure (). Например:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); this.setMeasuredDimension(parentWidth/2, parentHeight); this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight)); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Так что это правильный путь? Для меня ни один подход не работал на 100%.

Я думаю, действительно, что я спрашиваю, знает ли кто-нибудь из учебника, объясняющего onMeasure (), макет, размеры детских представлений и т. Д.?

Solutions Collecting From Web of "Уверенный способ переопределить onMeasure ()?"

Другие решения не являются исчерпывающими. Они могут работать в некоторых случаях, и это хорошее место для начала, но они, возможно, не гарантируют работу.

Когда onMeasure вызывается, вы можете или не иметь права изменять размер. Значения, передаваемые вашему onMeasure ( widthMeasureSpec , heightMeasureSpec ), содержат информацию о том, что разрешено вашему дочернему виду. В настоящее время существует три значения:

  1. MeasureSpec.UNSPECIFIED – вы можете быть настолько большими, насколько хотите.
  2. MeasureSpec.AT_MOST – настолько большой, насколько вы хотите (до размера спецификации). Это parentWidth в вашем примере.
  3. MeasureSpec.EXACTLY – Нет выбора. Родитель выбрал.

Это делается для того, чтобы Android мог сделать несколько проходов, чтобы найти нужный размер для каждого элемента, более подробно см. Здесь .

Если вы не соблюдаете эти правила, ваш подход не гарантирует работу.

Например, если вы хотите проверить, разрешено ли вообще изменить размер, вы можете сделать следующее:

 final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY; boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY; 

Используя эту информацию, вы узнаете, можете ли вы изменить значения, как в вашем коде. Или если вам требуется сделать что-то другое. Быстрый и простой способ решить нужный размер – использовать один из следующих способов:

Int resolveSizeAndState (int size, int measureSpec, int childMeasuredState)

Int resolveSize (int size, int measureSpec)

В то время как первый доступен только на Honeycomb, второй доступен для всех версий.

Примечание. Вы можете обнаружить, что resizeWidth или resizeHeight всегда являются ложными. Я обнаружил, что это так, если я запрашиваю MATCH_PARENT . Я смог исправить это, запросив WRAP_CONTENT на моем родительском макете, а затем во время этапа Integer.MAX_VALUE запрашивающего размер Integer.MAX_VALUE . Это дает максимальный размер, который позволяет ваш родитель на следующем прохождении через onMeasure.

Документация является авторитетом по этому вопросу: http://developer.android.com/guide/topics/ui/how-android-draws.html и http://developer.android.com/guide/topics/ui/custom -components.html

Подводя итог: в конце вашего переопределенного метода onMeasure вы должны вызвать setMeasuredDimension .

Вы не должны называть super.onMeasure после вызова setMeasuredDimension , который просто setMeasuredDimension , что вы установили. В некоторых ситуациях вы можете сначала вызвать super.onMeasure а затем изменить результаты, вызвав setMeasuredDimension .

Не вызывайте setLayoutParams в onMeasure . Макет происходит во втором проходе после измерения.

Если изменить размер просмотров внутри onMeasure все, что вам нужно, это вызов setMeasuredDimension . Если вы меняете размер за пределами onMeasure вам нужно вызвать setLayoutParams . Например, изменение размера текстового вида при изменении текста.

Зависит от используемого вами элемента управления. Инструкции в документации работают для некоторых элементов управления (TextView, Button, …), но не для других (LinearLayout, …). Способ, который работал очень хорошо для меня, состоял в том, чтобы назвать супер, как только я закончу. На основе статьи в приведенной ниже ссылке.

http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html

Вот как я решил проблему:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { .... setMeasuredDimension( measuredWidth, measuredHeight ); widthMeasureSpec = MeasureSpec.makeMeasureSpec( measuredWidth, MeasureSpec.EXACTLY ); heightMeasureSpec = MeasureSpec.makeMeasureSpec( measuredHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

}

Кроме того, это необходимо для компонента ViewPager

Я думаю, это зависит от родителя, что вы переопределяете.

Например, если вы расширяете ViewGroup (например, FrameLayout), когда вы измеряете размер, вы должны позвонить, как показано ниже

 super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 

Потому что вы можете захотеть, чтобы ViewGroup выполнял работу по отдыху (делайте некоторые вещи на детском представлении)

Если вы расширяете представление (например, ImageView), вы можете просто вызвать this.setMeasuredDimension(width, height); , Потому что родительский класс просто сделает что-то вроде обычного.

super.onMeasure() словом, если вам нужны некоторые функции, предлагаемые вашим родительским классом, вы должны вызвать super.onMeasure() (обычно пропустите MeasureSpec.EXACTLY), иначе вызовите this.setMeasuredDimension(width, height); достаточно.

Я думаю, setLayoutParams и перерасчет измерений – это временное решение, позволяющее правильно изменить дочерние представления, поскольку это обычно делается в onMeasure производного класса.

Тем не менее, это редко работает правильно (по какой-то причине …), лучше вызывать measureChildren (при получении ViewGroup) или попробовать что-то подобное, когда это необходимо.

Вы можете взять этот кусок кода в качестве примера onMeasure () ::

 public class MyLayerLayout extends RelativeLayout { public MyLayerLayout(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); int currentChildCount = getChildCount(); for (int i = 0; i < currentChildCount; i++) { View currentChild = getChildAt(i); //code to find information int widthPercent = currentChildInfo.getWidth(); int heightPercent = currentChildInfo.getHeight(); //considering we will pass height & width as percentage int myWidth = (int) Math.round(parentWidth * (widthPercent / 100.0)); int myHeight = (int) Math.round(parentHeight * (heightPercent / 100.0)); //Considering we need to set horizontal & vertical position of the view in parent AlignmentTraitValue vAlign = currentChildInfo.getVerticalLocation() != null ? currentChildlayerInfo.getVerticalLocation() : currentChildAlignmentTraitValue.TOP; AlignmentTraitValue hAlign = currentChildInfo.getHorizontalLocation() != null ? currentChildlayerInfo.getHorizontalLocation() : currentChildAlignmentTraitValue.LEFT; int topPadding = 0; int leftPadding = 0; if (vAlign.equals(currentChildAlignmentTraitValue.CENTER)) { topPadding = (parentHeight - myHeight) / 2; } else if (vAlign.equals(currentChildAlignmentTraitValue.BOTTOM)) { topPadding = parentHeight - myHeight; } if (hAlign.equals(currentChildAlignmentTraitValue.CENTER)) { leftPadding = (parentWidth - myWidth) / 2; } else if (hAlign.equals(currentChildAlignmentTraitValue.RIGHT)) { leftPadding = parentWidth - myWidth; } LayoutParams myLayoutParams = new LayoutParams(myWidth, myHeight); currentChildLayoutParams.setMargins(leftPadding, topPadding, 0, 0); currentChild.setLayoutParams(myLayoutParams); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }