- 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 ответов:
- 支持不同的屏幕尺寸
- 创建灵活的布局
- 使用 ConstraintLayout
- 避免使用硬编码的布局尺寸
- 创建备用布局
- 使用最小宽度限定符
- 使用可用宽度限定符
- 添加屏幕方向限定符
- 使用 Fragment 将界面组件模块化
- 使用旧尺寸限定符支持 Android 3.1
- 使用布局别名
- 创建可拉伸的九宫格位图
- 针对所有屏幕尺寸进行测试
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
используйте ниже код, это дает размер представления.
Источник
支持不同的屏幕尺寸
通过支持尽可能多的屏幕,您的应用可以在各种不同设备上运行,这样您就可以使用单个 APK 将其提供给最多的用户。此外,如果能够使您的应用灵活适应不同的屏幕尺寸,可确保您的应用可以处理设备上的窗口配置更改,例如,当用户启用多窗口模式时发生的窗口配置更改。
- 使用允许布局调整大小的视图尺寸
- 根据屏幕配置创建备用界面布局
- 提供可以随视图一起拉伸的位图
创建灵活的布局
使用 ConstraintLayout
如需创建适用于不同屏幕尺寸的自适应布局,最佳做法是将 ConstraintLayout 用作界面中的基本布局。使用 ConstraintLayout ,您可以根据布局中视图之间的空间关系指定每个视图的位置和大小。通过这种方式,当屏幕尺寸改变时,所有视图都可以一起移动和拉伸。
如需使用 ConstraintLayout 构建布局,最简单的方法是使用 Android Studio 中的布局编辑器。借助该工具,您可以将新视图拖动到布局中,将其约束条件附加到父视图和其他同级视图以及修改视图的属性,完全不必手动修改任何 XML(请参见图 1)。
图 1. Android Studio 中的布局编辑器,显示了一个 ConstraintLayout 文件
但是, ConstraintLayout 并不能解决所有布局场景(特别是动态加载的列表,对于此类布局,应使用 RecyclerView),但无论您使用何种布局,都应该避免对布局尺寸进行硬编码(请参见下一部分)。
避免使用硬编码的布局尺寸
为了确保布局能够灵活地适应不同的屏幕尺寸,您应该对大多数视图组件的宽度和高度使用 «wrap_content» 和 «match_parent» ,而不是硬编码的尺寸。
虽然此视图的实际布局取决于其父视图和任何同级视图中的其他属性,但是此 TextView 想要将其宽度设为填充所有可用空间 ( match_parent ),并将其高度设为正好是文本长度所需的空间 ( wrap_content )。这样可以使此视图适应不同的屏幕尺寸和不同的文本长度。
图 2 显示了当屏幕宽度随着设备屏幕方向而发生变化时,如何使用 «match_parent» 调整文本视图的宽度。
图 2. 灵活的文本视图
如果您使用的是 LinearLayout ,则也可以按布局权重展开子视图,以便每个视图按自身权重值所占的比例填充剩余的空间。但是,在嵌套的 LinearLayout 中使用权重将要求系统执行多次布局遍历以确定每个视图的尺寸,这会降低界面性能。幸运的是, ConstraintLayout 几乎能够构建 LinearLayout 所能构建的所有布局,而不会影响性能,因此您应该尝试将布局转换为 ConstraintLayout。然后,即可使用约束链来定义加权布局。
注意 :使用 ConstraintLayout 时,不得使用 match_parent 。而应将尺寸设为 0dp 以启用一种称为“匹配约束”的特殊行为,该行为通常与 match_parent 的预期行为相同。如需了解详情,请参阅如何调整 ConstraintLayout 中的视图尺寸。
创建备用布局
图 3. 同一应用显示在尺寸不同的屏幕上,针对每种屏幕尺寸使用不同的布局
您可以通过创建额外的 res/layout/ 目录提供特定于屏幕的布局(针对需要不同布局的每种屏幕配置创建一个目录),然后将屏幕配置限定符附加到 layout 目录名称(例如,对于可用宽度为 600dp 的屏幕,附加限定符为 layout-w600dp )。
如需在 Android Studio(使用 3.0 或更高版本)中创建备用布局,请按以下步骤操作:
- 打开默认布局,然后点击工具栏中的 Orientation for Preview 图标 。
- 在下拉列表中,点击以创建一个建议的变体(如 Create Landscape Variant),或点击 Create Other。
- 如果您选择 Create Other,系统将显示 Select Resource Directory。在此窗口中,在左侧选择一个屏幕限定符,然后将其添加到 Chosen qualifiers 列表中。添加限定符之后,点击 OK。(有关屏幕尺寸限定符的信息,请参阅下面几部分。)
使用最小宽度限定符
使用“最小宽度”屏幕尺寸限定符,您可以为具有最小宽度(以密度无关像素 dp 或 dip 为度量单位)的屏幕提供备用布局。
例如,您可以创建一个名为 main_activity 且针对手机和平板电脑进行了优化的布局,方法是在目录中创建该文件的不同版本,如下所示:
- 320dp:典型手机屏幕(240×320 ldpi、320×480 mdpi、480×800 hdpi 等)。
- 480dp:约为 5 英寸的大手机屏幕 (480×800 mdpi)。
- 600dp:7 英寸平板电脑 (600×1024 mdpi)。
- 720dp:10 英寸平板电脑(720×1280 mdpi、800×1280 mdpi 等)。
图 4 提供了一个更详细的视图,说明了不同屏幕 dp 宽度与不同屏幕尺寸和方向的一般对应关系。
图 4. 建议的宽度断点以支持不同的屏幕尺寸
使用可用宽度限定符
您可能希望根据当前可用的宽度或高度来更改布局,而不是根据屏幕的最小宽度来更改布局。 例如,如果您有一个双窗格布局,您可能希望在屏幕宽度至少为 600dp 时使用该布局,但屏幕宽度可能会根据设备的屏幕方向是横向还是纵向而发生变化。在这种情况下,您应使用“可用宽度”限定符,如下所示:
如果您关心可用高度,则可以使用“可用高度”限定符来执行相同的操作。例如,对于屏幕高度至少为 600dp 的屏幕,请使用限定符 layout-h600dp 。
添加屏幕方向限定符
为此,您可以将 port 或 land 限定符添加到资源目录名称中。只需确保这些限定符在其他尺寸限定符后面即可。 例如:
使用 Fragment 将界面组件模块化
在针对多种屏幕尺寸设计应用时,您希望确保不会在 Activity 之间不必要地重复界面行为。因此,您应该使用 Fragment 将界面逻辑提取到单独的组件中。然后,您可以组合 Fragment 以便在大屏幕设备上运行时创建多窗格布局,或者在手机上运行时将 Fragment 放置在单独的 Activity 中。
使用旧尺寸限定符支持 Android 3.1
如果您的应用支持 Android 3.1(API 级别 12)或更低版本,则除上面的最小/可用宽度限定符之外,您还需要使用旧尺寸限定符。
在上面的示例中,如果要在较大的设备上显示双窗格布局,那么您需要使用“large”配置限定符来支持 3.1 及更低版本。因此,要在这些旧版本上实现此类布局,您可能需要创建以下文件:
使用布局别名
如果同时支持低于和高于 Android 3.2 的版本,您必须同时对布局使用最小宽度限定符和“large”限定符。因此,您应创建一个名为 res/layout-large/main.xml 的文件,该文件可能与 res/layout-sw600dp/main.xml 完全相同。
这两个文件的内容完全相同,但它们实际上并未定义布局,而只是将 main 设置为 main_twopanes 的别名。由于这些文件具有 large 和 sw600dp 选择器,因此它们适用于任何 Android 版本的平板电脑和电视(低于 3.2 版本的平板电脑和电视与 large 匹配,高于 3.2 版本者将与 sw600dp 匹配)。
创建可拉伸的九宫格位图
如果您在改变尺寸的视图中将位图用作背景,您会注意到,当视图根据屏幕尺寸或视图中的内容增大或缩小时,Android 会缩放您的图片。这通常会导致明显的模糊或其他缩放失真。解决方案是使用九宫格位图,这种特殊格式的 PNG 文件会指示哪些区域可以拉伸,哪些区域不可以拉伸。
九宫格位图基本上是一种标准的 PNG 文件,但带有额外的 1 像素边框,指示应拉伸哪些像素(并且带有 .9.png 扩展名,而不只是 .png )。如图 5 中所示,左边缘和上边缘的黑线之间的交点是可以拉伸的位图区域。
图 5. 九宫格图片 ( button.9.png )
针对所有屏幕尺寸进行测试
如果您希望在物理设备上进行测试,但又不想购买设备,则可以使用 Firebase 测试实验室访问 Google 数据中心内的设备。
Источник