Android不同屏幕尺寸/分辨率的适配方法,如何减少工作量

3
很不幸,当我的应用程序已经完成并完全可用时,我却遇到了不同的屏幕尺寸问题。
我找到了成千上万个有关不同设备/分辨率/dpi实现的答案,并尝试从中学习一些东西。
我的目标是不使用不同密度文件夹,而是为每个布局分辨率/dpi调整/重新定位已有图片。由于缩放引起的图片轻微模糊目前对我来说不重要。我的应用程序是一个学校项目,我需要在几天内开始它。
我的想法是创建一个巨大的布局文件夹集合,例如:
layout-normal-mdpi    
layout-normal-hdpi
layout-normal-xhdpi
layout-normal-xxhdpi
layout-normal-xxxhdpi
layout-large-mdpi
layout-large-hdpi
layout-large-xhdpi
layout-large-xxhdpi
layout-large-xxxhdpi
layout-xlarge-mdpi
layout-xlarge-hdpi
layout-xlarge-xhdpi
layout-xlarge-xxhdpi
layout-xlarge-xxxhdpi

请将我的活动复制/粘贴到那里,并设置每个活动对象的所需DP值,以使该应用程序可在大多数设备上使用/查看。
之后,我将创建尽可能多的虚拟设备来正确测试和编辑图形。
好吧,再说一遍,我通过这种方式失去了什么(除了质量DPI分辨率)?
您有更好的想法使我的应用程序与大多数设备兼容吗?
我的应用程序主要针对平板电脑,并希望使其与4英寸以上的手机兼容。
最后一个问题:
像我这样使用密度值: layout-normal-hdpi
是一个好的做法吗?它将在未来的Android版本中实现吗?还是最好避免使用像这样的DPI值: layout-normal
非常感谢任何帮助。
这是我创建的Galaxy S7 Edge虚拟设备的屏幕截图。它自己加载layout-normal-xxxhdpi布局。

enter image description here


1
这是我最近看到的关于复杂布局需要“设备特定”视图大小和位置的最佳Android布局相关SO帖子之一。Leodev的答案可以真正减少臃肿的res文件夹,并且应该成为创建需要使用swXXXdp方法的布局文件夹的协议的一部分。 - whyoz
3个回答

3
我建议您不要创建所有这些布局,而是创建不同的dimens.xml文件。这样,您只需要创建一个布局,并为每个视图创建一个size属性,Android会根据设备屏幕尺寸自动获取它。以下是一个示例:
布局:
<ImageView
        android:id="@+id/image_cat"
        android:layout_width="@dimen/width_category_image_carousel"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:foregroundGravity="center_horizontal|bottom" />

文件DIMENS.XML适用于sw300dp(表示无论方向如何,最小宽度都必须为300dp)

<resources >
    <dimen name="width_category_image_carousel">220dp</dimen>
</resources>

您需要在资源目录中的值目录中创建更多的dimens.xml文件,以支持不同尺寸的屏幕。 您可以在此处找到有关如何定义不同dimens的更多信息: https://developer.android.com/guide/practices/screens_support.html#NewQualifiers


嗨@LG89,这个答案听起来对我很有趣!无论如何,我有一些问题:以一个尺寸文件为例: res/values-sw720dp/dimens.xml 这在像720x1280这样的设备上运行得很好,但在另一个设备上(如1400x900)会产生完全相同的图形吗?同样的图形会自动调整大小吗?还是我必须创建一个 res/values-sw900dp/dimens.xml - WizardingStudios
首先,使用dp作为单位进行测量会在具有不同像素密度的设备上创建不同的大小,因此基本上,对于您的第一个问题的答案是否定的,在720x1280和1400x900中它不会产生相同的图形,但不会影响dimens文件,而是会影响dp的定义。 然后,如果您的意思是尺寸值在720x1280和1400x900中将保持相同,那么是的,例如120dp值对于第一个设备和第二个设备将保持相同,因此,如果您想要更好的布局,则需要创建其他维度文件。 - leodev
再次感谢,我正在实现你的答案,结果非常好...但是...我正在使用Android Studio进行测试,虚拟设备是Galaxy S7 Edge,屏幕尺寸为1440x2560。我尝试创建一个名为res/values-sw1400dp/dimens.xml的值文件夹,但编辑器没有改变任何内容。我也尝试了res/values-sw1000dp/dimens.xmlres/values-sw720dp/dimens.xml,结果仍然是一样的。最后,我尝试了res/values-xxxhdpi/dimens.xml,它完美地工作!我错过了什么吗?我不想失去使用SW方法来获得更多dimen的可能性... - WizardingStudios
你说得对,我的朋友。再次感谢你的帮助,你的解决方案最优雅且资源消耗最少。它按预期工作,我非常喜欢它! - WizardingStudios
最后一个问题,请问:在您的代码中有 **android:layout_weight="2"**。我认为这是不必要的,我是对的吗? - WizardingStudios
显示剩余4条评论

0
再说一遍,我这样做会失去什么(除了质量DPI分辨率)?
布局可能完全不同。有些视图可能超出屏幕范围。某些文本可能不包含在它们的布局中。当然,ImageViewswill将被拉伸得像地狱一样。
你有更好的想法让我的应用程序兼容大多数设备吗?
是的。您可以基于属性layout_weight构建您的布局。

https://developer.android.com/guide/topics/ui/layout/linear.html

这适用于LinearLayout,但在RelativeLayout中的使用方式略有不同。 此属性的目标是为布局中的每个视图分配总大小的一定百分比。

使用示例。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:weightSum="5">

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="1" />

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:text="2" />

    <ImageView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="3" />

    </LinearLayout>

这样,您就可以构建适应每个屏幕大小和密度的UI。

但是要小心,使用此属性时会有警告。如果您在嵌套布局中使用layout_weight属性,则视图渲染的性能将显著降低。

为什么嵌套权重对性能不利?有替代方案吗?


非常感谢,但我所有的活动都是使用RelativeLayout。 - WizardingStudios

0

假设您关心的是图像的质量,因为您根据可用空间调整它们的大小,我建议执行以下操作:

  1. 如果您有一张图片需要适应设备宽度,我会将这些图片放在res/drawable-nodpi文件夹中,例如image1_360.png、image1_540.png、image1_720.png和image1_1080.png。
  2. 在res/values文件夹中,我会创建一个drawables.xml文件,其中包含以下内容:

    <drawable name="image1">@drawable/image1_360</drawable>
    
在values-hdpi中,我会用另一张图片替换它。
    <drawable name="image1">@drawable/image1_540</drawable>

同样适用于xhdpi和xxhdpi

  • 在 values-w600dp 中,我将用以下代码替换该图像:

    <drawable name="image1">@drawable/image1_540</drawable>
    
  • 对于更高密度的桶也是同样的处理方式

  • 在 values-w720dp 中,我将用以下代码替换该图像:

    <drawable name="image1">@drawable/image1_720</drawable>
    
  • 对于值为w720dp-hdpi的情况

        <drawable name="image1">@drawable/image1_1080</drawable>
    
  • 在 values-w1000dp 中,我会用以下代码替换该图片:

    <drawable name="image1">@drawable/image1_1080</drawable>
    
  • 这可能会因实际需求而有所不同,但思路是使用values文件夹来适配不同的屏幕尺寸和像素密度组合,并使用drawable XML标签引用可绘制资源。

    谢谢Piotr,我认为这与创建各种可绘制的文件夹相同,每个DPI值一个文件夹。有了这个答案,我必须在我的应用程序中存储大量图片。 - WizardingStudios
    我认为问题在于你必须为每个 DPI 桶 x 3(手机、小型和大型平板电脑)存储可绘制对象。这个解决方案允许您限制实际使用的可绘制对象数量。 - Piotr Zawadzki
    是的,我应该限制在手机、小型和大型平板电脑上。无论如何,被接受的答案只需要每个尺寸一个图片。有时候缩放方法会产生丑陋的结果,在下一个项目中,我将直接从sw900dp图片开始,以限制缩放图形问题。非常感谢。 - WizardingStudios

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接