onMeasure пользовательский вид пояснения

Я попытался выполнить пользовательский компонент. Я расширил class View и сделаю некоторый рисунок в onDraw . Почему мне нужно переопределить onMeasure ? Если бы я этого не сделал, все было бы правильно. Может кто-нибудь объяснить это? Как написать мой метод onMeasure ? Я видел пару учебников, но каждый из них немного отличается от другого. Иногда они называют super.onMeasure в конце, иногда они используют setMeasuredDimension и не называют это. Где разница?

В конце концов, я хочу использовать несколько точно таких же компонентов. Я добавил эти компоненты в свой XML файл, но я не знаю, насколько они велики. Я хочу установить его положение и размер позже (почему мне нужно установить размер в onMeasure если в onDraw когда я его рисую, также работает) в пользовательском classе компонента. Когда мне это нужно?

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 или 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); } 

Надеюсь, это поможет.

на самом деле, ваш ответ не является полным, поскольку значения также зависят от контейнера упаковки. В случае относительных или линейных макетов значения ведут себя так:

  • ТОЧНО match_parent ТОЧНО + размер родителя
  • AT_MOST wrap_content приводит к AT_MOST MeasureSpec
  • UNSPECIFIED никогда не запускается

В случае горизонтальной прокрутки ваш код будет работать.

  • Как получить выбранный элемент в ListView?
  • listView динамический элемент добавления
  • BaseAdapter заставляет ListView выходить из строя при прокрутке
  • Мой IAP не работает. Ошибки в func Paymentqueue
  • Android - динамически добавлять виды в представление
  • ListView setOnItemClickListener не работает, добавив кнопку
  • Android SDK 22 - проблемы с визуализацией SearchView
  • Как загрузить Listview «плавно» в android
  • Что такое строго типизированный вид в ASP.NET MVC
  • TextView с различным textSize
  • Скрыть нижний колонтитул в ListView?
  • Interesting Posts
    Давайте будем гением компьютера.