- GetWidth () и getHeight () из View возвращает 0
- 1. Слушайте события Draw / Layout: ViewTreeObserver
- 2. Добавьте runnable в очередь макета: View.post ()
- 3. Заменить метод onLayout Views
- 4. Проверьте, прошел ли этап компоновки
- Дополнительно: получение статически определенных измерений
- Tek Eye
- Determining the Size of an Android View or Screen at Run Time
- Finding the Size of an Android View in Code
- Finding the Size of an Android Layout in Code
- Finding the Size of an Android View During Screen Construction
- See Also
- Archived Comments
- Do you have a question or comment about this article?
- Определение размера представления Android во время выполнения
- 10 ответов:
GetWidth () и getHeight () из View возвращает 0
Я динамически создаю все элементы в моем проекте Android. Я пытаюсь получить ширину и высоту кнопки, чтобы я мог повернуть эту кнопку вокруг. Я просто пытаюсь научиться работать с языком Android. Однако он возвращает 0.
Я провел некоторое исследование, и я увидел, что это нужно сделать где-то иначе, чем в onCreate() . Если кто-то может дать мне пример того, как это сделать, это было бы здорово.
Вот мой текущий код:
Любая помощь приветствуется.
Вы вызываете getWidth() слишком рано. Пользовательский интерфейс еще не был отмерен и выложен на экране.
Я сомневаюсь, что вы хотите делать то, что вы делаете, так или иначе – виджеты, анимированные, не меняют свои интерактивные области, поэтому кнопка будет реагировать на клики в исходной ориентации независимо от того, как она вращается.
При этом вы можете использовать ресурс измерения для определения размера кнопки, а затем ссылаться на этот ресурс измерения из вашего файла макета и исходного кода, чтобы избежать этой проблемы.
Основная проблема заключается в том, что вам нужно подождать фазы рисования для фактических измерений (особенно с динамическими значениями, такими как wrap_content или match_parent ), но обычно эта фаза не была доведена до onResume() . Поэтому вам нужно обходное решение для ожидания этой фазы. Существуют разные возможные решения:
1. Слушайте события Draw / Layout: ViewTreeObserver
ViewTreeObserver запускается для разных событий рисования. Обычно OnGlobalLayoutListener – это то, что вы хотите получить для измерения, поэтому код в слушателе будет вызван после фазы компоновки, поэтому измерения будут готовы:
Примечание. Слушатель будет немедленно удален, потому что иначе он будет срабатывать при каждом событии макета. Если вам нужно поддерживать приложения SDK Lvl
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Добавьте runnable в очередь макета: View.post ()
Не очень хорошо известно и мое любимое решение. В основном просто используйте метод публикации «Вид» со своей собственной версией. Это в основном очереди вашего кода после измерения, макета и т. Д., Как заявляет Ромен Гай :
Очередь событий пользовательского интерфейса будет обрабатывать события по порядку. После вызова setContentView () очередь событий будет содержать сообщение с запросом на ретрансляцию, поэтому все, что вы отправляете в очередь, произойдет после прохода макета
Преимущество над ViewTreeObserver :
- Ваш код выполняется только один раз, и вам не нужно отключать Наблюдателя после выполнения, что может быть проблемой
- Менее подробный синтаксис
3. Заменить метод onLayout Views
Это практично только в определенной ситуации, когда логика может быть инкапсулирована в самом представлении, иначе это довольно многословный и громоздкий синтаксис.
Также помните, что onLayout будет вызываться много раз, поэтому будьте внимательны к тому, что вы делаете в методе, или отключите свой код после первого раза
4. Проверьте, прошел ли этап компоновки
Если у вас есть код, который выполняется несколько раз при создании ui, вы можете использовать следующий метод поддержки v4 lib:
Возвращает true, если представление прошло по крайней мере с одного макета, поскольку оно было последним прикреплено к окну или отсоединено от него.
Дополнительно: получение статически определенных измерений
Если достаточно просто получить статически определенную высоту / ширину, вы можете просто сделать это с помощью:
Но помните, что это может отличаться от фактической ширины / высоты после рисования. Javadoc отлично описывает разницу:
Размер представления выражается шириной и высотой. В представлении фактически есть две пары значений ширины и высоты.
Первая пара известна как измеренная ширина и измеренная высота. Эти размеры определяют, как большой вид хочет быть внутри своего родителя (см. Макет для более подробной информации.) Измеренные размеры можно получить, вызвав getMeasuredWidth () и getMeasuredHeight ().
Вторая пара просто известна как ширина и высота, иногда ширина рисунка и высота рисунка. Эти размеры определяют фактический размер представления на экране, время рисования и после макета. Эти значения могут, но не обязательно, отличаться от измеренной ширины и высоты. Ширина и высота можно получить, вызвав getWidth () и getHeight ().
Мы можем использовать
Я использовал это решение, которое, я думаю, лучше, чем onWindowFocusChanged (). Если вы откроете DialogFragment, затем поверните телефон, onWindowFocusChanged будет вызываться только тогда, когда пользователь закрывает диалог):
Изменить: поскольку removeGlobalOnLayoutListener устарел, вы должны теперь:
Как заявляет Ян в этой статье разработчиков Android :
Во всяком случае, дело в том, что компоновка содержимого окна происходит после того, как все элементы построены и добавлены к их родительским представлениям. Это должно быть так, потому что, пока вы не узнаете, какие компоненты содержит вид, и что они содержат, и так далее, нет разумного способа выложить его.
В нижней строке, если вы вызываете getWidth () и т. Д. В конструкторе, он будет возвращать ноль. Процедура состоит в том, чтобы создать все элементы вашего представления в конструкторе, а затем дождаться, когда будет вызван метод OnSizeChanged (), который вы хотите увидеть, – вот когда вы впервые узнаете свой реальный размер, так что вы устанавливаете размеры ваших элементов графического интерфейса.
Имейте в виду, что onSizeChanged () иногда вызывается с параметрами zero-check для этого случая и немедленно возвращается (так что вы не получаете деления на ноль при расчете вашего макета и т. Д.). Через некоторое время он будет вызываться с реальными значениями.
Если вам нужно получить ширину какого-либо виджета перед его отображением на экране, вы можете использовать getMeasuredWidth () или getMeasuredHeight ().
Я предпочел бы использовать OnPreDrawListener() вместо addOnGlobalLayoutListener() , поскольку он вызывается раньше.
Источник
Tek Eye
For efficient bitmap handling or dynamic View creation in an app, the area that a screen item or layout is using needs to be known. If no fixed sizes are allocated at design time the size of a View may not be known until an app is executed. This is because of the wide range of display sizes that Android supports. Just look on GSMArena to see the huge range of Android devices produced over the years, and to see the wide variation in screen sizes and pixel densities. The example code in this article shows how to read the screen size and the size of Views as the app runs.
(Note: All Android screen items are derived from Views. A screen component, e.g. a TextView , is derived from the View class. Such screen components are also known as widgets. Layouts are ViewGroups and are also derived from Views.)
Determining the Size of an Android View or Screen at Run Time
To run the example code in this article first create a new Android project. Those new to Android programming can read the article Your First Android Hello World Java Program to see how. For this article the app is called View Size.
Use a simple layout for activity_main.xml (the layout file may have another name). Add a TextView with id labXY and set the Text attribute to X,Y. Next to it add another TextView called textXY with Text set to ? (actually \? to make it valid in the XML). Here is the layout used for this example:
Add this code to the bottom of the onCreate method in MainActivity.java (or whatever the class was called). Add the required an imports for TextView and DisplayMetrics when prompted with the Alt-Enter:
This is the code running on an Android Virtual Device (AVD) with a 320×480 screen:
Finding the Size of an Android View in Code
Drop an ImageView onto the layout, here using the ic_launcher.png icon file, or other images can be used. The size of a View can be retrieved using the getWidth and getHeight methods. Change the code in the onCreate to set the TextView to the ImageView’s width and height (an import for View is required, again usually prompted for and added with Alt-Enter):
Mmmmm! The code is showing 0,0 for the ImageView size, even though we can see that it is not 0,0:
This is because in onCreate the screen has not yet been laid out so the size of the ImageView has not been determined hence the getWidth() and getHeight() methods are returning zero. In fact they will likely return zero in onStart() and onResume(). What is needed is to override onWindowFocusChanged() to get the ImageView sizes:
Finding the Size of an Android Layout in Code
The same code can be used to get the size of the View (the layout, i.e. ViewGroup) in which the screen components sit. Notice that in the screen XML the RelativeLayout was given an id (@+id/screen), which means the base View’s width and height can be grabbed (change R.id.imageView to R.id.screen in the code):
Notice that the layout height is less than the screen height because of the notification bar.
Finding the Size of an Android View During Screen Construction
To get the the size of a View as soon as it is known (rather than waiting for the onWindowFocusChanged event) attach a listener to its ViewTreeObserver . Do this by writing a class that implements ViewTreeObserver.OnGlobalLayoutListener in the Activity’s class. This new class will have an onGlobalLayout method that gets the View dimensions that can then be stored for later use (here they are displayed as before). Here is the example source code for the entire MainActivity.java file to show this way of getting the ImageView’s width and height:
Download some example code in view-size.zip from this article, ready for importing into Android Studio. See the instructions in the zip file, alternatively the code can also be accessed via the Android Example Projects page.
See Also
- Using Immersive Full-Screen Mode on Android Developers
- See the Android Example Projects page for lots of Android sample projects with source code.
- For a full list of all the articles in Tek Eye see the full site alphabetical Index.
Archived Comments
Kestrel on December 15, 2014 at 4:20 am said: Hey fantastic article, can you also talk about the fitSystemWindows and how things are affected when its set or not set by default. Thanks in advance.
Author: Daniel S. Fowler Published: 2013-06-19 Updated: 2017-12-17
Do you have a question or comment about this article?
(Alternatively, use the email address at the bottom of the web page.)
↓markdown↓ CMS is fast and simple. Build websites quickly and publish easily. For beginner to expert.
Free Android Projects and Samples:
Источник
Определение размера представления Android во время выполнения
Я пытаюсь применить анимацию к представлению в моем приложении для Android после создания моей активности. Для этого мне нужно определить текущий размер представления, а затем настроить анимацию для масштабирования от текущего размера до нового размера. Эта часть должна быть выполнена во время выполнения, так как вид масштабируется до разных размеров в зависимости от ввода от пользователя. Мой макет определен в XML.
это кажется легкой задачей, и есть много так вопросов относительно этого, хотя никто что, очевидно, решило мою проблему. Так что, возможно, я упускаю что-то очевидное. Я получаю ручку к моему взгляду:
это работает нормально, но при вызове getWidth() , getHeight() , getMeasuredWidth() , getLayoutParams().width и т. д. все они возвращают 0. Я также попытался вручную позвонить measure() на вид с последующим вызовом getMeasuredWidth() , но это не имеет никакого эффекта.
Я попытался вызвать эти методы и проверить объект в отладчике в моей деятельности onCreate() и onPostCreate() . Как может Я выясняю точные размеры этого представления во время выполнения?
10 ответов:
используйте ViewTreeObserver на представлении, чтобы дождаться первого макета. Только после того, как первый макет будет getWidth()/getHeight()/getMeasuredWidth()/getMeasuredHeight() работы.
Существует несколько решений, в зависимости от сценария:
- безопасный метод, будет работать непосредственно перед рисованием Вида, после завершения этапа компоновки:
- в некоторых случаях, достаточно измерить размер вручную:
- если у вас есть пользовательский вид, который вы расширили, вы можете получите его размер по методу «onMeasure», но я думаю, что он хорошо работает только в некоторых случаях:
если вы пишете в Kotlin, вы можете использовать следующую функцию, которая за кулисами работает точно так же, как runJustBeforeBeingDrawn что я написал:
обратите внимание, что вам нужно добавить это в gradle (найдено через здесь):
ты называешь getWidth() прежде чем вид на самом деле выложен на экране?
распространенной ошибкой новых разработчиков Android является использование ширины и высота вида внутри его конструктора. Когда представление конструктор называется, Android еще не знает, насколько большой вид будет быть, поэтому размеры установлены на ноль. Реальные размеры рассчитываются во время этап компоновки, который происходит после строительства, но перед чем-либо почерпнутый. Вы можете использовать onSizeChanged() метод уведомления значения, когда они известны, или вы можете использовать getWidth() и getHeight() методы позже, например в onDraw() метод.
на основе рекомендаций @mbaird, я нашел приемлемое решение путем создания подклассов ImageView класса и переопределение onLayout() . Затем я создал интерфейс наблюдателя, который моя активность реализовала и передала ссылку на себя классу, что позволило ему сообщить активность, когда она была фактически завершена.
Я не на 100% убежден, что это лучшее решение (поэтому я пока не отмечаю этот ответ как правильный), но он работает и согласно документации первый раз, когда можно найти фактический размер представления.
вот код для получения макета путем переопределения представления, если API
вы можете проверить этот вопрос. Вы можете использовать View ‘ s post () метод.
это работает для меня в моем onClickListener :
Я тоже потерялся вокруг getMeasuredWidth() и getMeasuredHeight() getHeight() и getWidth() в течение длительного времени. позже я обнаружил, что получение ширины и высоты в onSizeChanged() это лучший способ, чтобы сделать это. вы можете динамически получить текущую ширину и текущую высоту вашего представления, переопределив onSizeChanged( ) метод.
возможно, вы захотите взглянуть на это, у которого есть сложный фрагмент кода. Новое сообщение в блоге: Как получить размеры ширины и высоты customView (extends View) в Android http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height-dimensions.html
используйте ниже код, это дает размер представления.
Источник