理解如何支持多屏幕

9
我知道有很多关于我的问题的吉比特信息,我几乎都看过了——官方文档、XDA-Developers和这里的帖子等等,但我仍然无法解决问题,希望你能为我解释一下。所以,我有一个主屏幕上带有仪表盘图标的应用程序,我需要让这个屏幕在所有现有的屏幕上看起来都一样,在这里是纵向和横向的标准:
![MAIN_PORTRAIT](https://istack.dev59.com/gU8ql.webp) ![MAIN_LAND](https://istack.dev59.com/CX8la.webp)
为了实现这个目标,我在我的项目中添加了下面的文件夹:
![enter image description here](https://istack.dev59.com/iQyEZ.webp)
我将所有大小,如图像大小、文本大小和边距都设置在dimens.xml文件中,以适应每个屏幕分辨率。我认为这足以在不同的设备上看到相同的图片。但我错了,在相同的分辨率但不同的屏幕尺寸上,它看起来不同。这里是一个3.2英寸和5.1英寸的mdpi屏幕:
![Screen 3.2"](https://istack.dev59.com/kqwJO.webp) ![Screen 5.1"](https://istack.dev59.com/maAez.webp)
我不确定是否应该添加像“values-mdpi-sw320dp”这样的文件夹,还是我需要了解其他的方法才能在所有屏幕上看到相同的图片?将所有大小都设置在dimens.xml文件中是否正确?请给我解释一下。谢谢。

请查看此链接- http://stackoverflow.com/questions/19065701/applying-resolution-for-different-devices/19065842#19065842 - Kanwaljit Singh
@KanwaljitSingh 我已经阅读了您在链接中的答案,似乎您没有理解我的问题。是的,您完全正确地使用了“设备分辨率”dimens,但如果您获得具有相同屏幕分辨率但不同屏幕尺寸的设备,您将怎么做?由于我已经为所有大小(图像、按钮等)使用了dimens,这使得问题变得复杂。 - whizzzkey
好的,请检查这个链接:http://stackoverflow.com/questions/15506786/how-do-i-create-different-layouts-for-4-and-10-displays-at-same-resolution - Kanwaljit Singh
@KanwaljitSingh对我来说仍然没有用,因为我不想创建像layout-hdpi-sw320dp layout-hdpi-sw480dp这样的多个布局,我认为更好的方法是使用一个布局但为其提供不同的尺寸。似乎在StackOverflow上没有人知道如何正确地支持多屏幕。 - whizzzkey
6个回答

4

您不需要指定所有这些不同的尺寸来实现像那样简单的屏幕。只需稍微调整布局即可。 例如,让我们看看您的第一个屏幕。您可以使用TableLayout或甚至是一个包含N个LinearLayout的垂直LinearLayout。此时只需使用权重! 例如:想要每行两行和每行三个正方形图像的网格:

<?xml version="1.0" encoding="utf-8"?>

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

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />
</LinearLayout>

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

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />

    <ImageView
        android:layout_width="0px"
        android:layout_height="wrap_content"
        android:layout_weight=".33" />
</LinearLayout>

很不幸,这仍然不足以满足您的需求。您可能还想实现的另一件事是使您的图像仍具有正方形比例。

要实现这一点,只需像这样扩展图像视图:

public class SquaredImageView extends ImageView {

public SquaredImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
             int width = MeasureSpec.getSize(widthMeasureSpec);
             int height = width;
             setMeasuredDimension(width, height);

}

现在只需提供适当密度的图像,一切都会看起来与您想要的完全相同。


谢谢您的回答,但是在3.2英寸和5.1英寸mdpi屏幕上,仍然存在不同屏幕图片的问题,因为图标(来自drawable-mdpi)对于5.1英寸来说太小了,当我增加它们的大小时,它看起来非常糟糕和丑陋(屏幕上会出现很多像素)。 - whizzzkey
对于这个问题,您可以使用不同的可绘制资源(这就是不同文件夹真正有用的地方)。只需将较大的mdpi图像放入名为drawables-swXXdp-mdpi的文件夹中,将XX替换为应使用该可绘制资源的最小dp大小即可。 - Pasquale Anatriello

1
我认为这个主题也很麻烦。正如你所说,你应该在应用程序中使用values-sw320dp-hdpivalues-sw320dp-xhdpivalues-sw320dp-xxhdpi等等。
最近,我在我正在工作的一个应用程序上也做了同样的事情,我发现Galaxy S2读取了values-sw320dp-hdpiGalaxy S4采用了values-sw320dp-xxhdpiGalaxy Note采用了values-sw320dp-xhdpi。因此,声明这些内容是必要的。
如果您想快速阅读,可以参考this。而this应用程序非常有帮助,因为它揭示了大多数设备的保密信息。

谢谢您的回答,但是有没有办法避免创建大量“克隆文件夹”,也许我错过了什么? - whizzzkey
很糟糕,无论它是什么,都应该得到一个+1的答案。 - whizzzkey

1
  1. 最小宽度限定符仅在Android 3.2及以上版本上可用,如果您的5.1英寸屏幕运行的操作系统版本早于3.2,则不会匹配正确的布局。

  2. 如果Android版本均>= 3.2,则layout_sw600dp或layout_sw720dp的布局文件并不是真正为其优化。从您提供的屏幕截图来看,某些UI元素的布局大小没有得到正确优化。


1
首先,屏幕尺寸并不重要,您需要确定屏幕密度,例如我的Sony Xperia Z的240+dpi。然后,您可以将它们与Android定义的最接近的桶匹配,例如240dpi-hdpi。
在您的情况下,桶是mdpi。只有一个drawable-mdpi中的可绘制集将适用于您的两个设备。
您看到的是正确的行为。您可能希望重新布局您的东西以适应更大的屏幕,例如有5行而不是3行。或者,您可以绘制更大的框架(每个图标160dp而不是100dp;您需要使用DisplayMetrics进行一些计算),并使用更高分辨率的图像来适应这些框架(这些图像需要在相同的drawable-mdpi文件夹中!)

1
谢谢,但问题在于图标在3.2英寸mdpi上看起来很好,但对于5.1英寸mdpi来说太小了。当我尝试增加它的大小时,它变得非常难看和丑陋(我看到了很多像素)。 - whizzzkey
好的,如果它们都是mdpi,从你的截图和3.2英寸和5.1英寸之间巨大的差异可以推断出,这两个设备的宽度和高度非常不同,例如一个设备的宽度为300dp,另一个设备的宽度为500dp。因此,在这里您确实需要使用宽度和高度的精确计算,例如 icon width = screen width/3,对于3.2英寸设备为100dp,对于5.1英寸设备为160dp。只需记住使用最高可能的分辨率的图像。 - ericn
请告诉我,我是否理解正确 - 我应该使用一个具有最高分辨率图像的“drawable”文件夹,而不是许多drawable-dpi文件夹,对吗? - whizzzkey
首先,只有一个可绘制集合(mdpi)将适用于您的情况!其次,通过这些计算,我谈论的是您放置图像的帧/框。 - ericn

0
如果权重不足以满足您的需求,考虑在代码中动态设置尺寸。您可以通过以下方式获取当前屏幕对角线长度:
    Display display = ((WindowManager) c.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    DisplayMetrics displayMetrics = new DisplayMetrics();
    display.getMetrics(displayMetrics);
    screenRect = new Rect(0, 0, width, height);
    screenDiagonal = Math.sqrt(width * width + height * height) / displayMetrics.densityDpi;

然后,您可以动态创建LayoutParams并根据此值应用大小于您的视图。我知道这有点hacky,使用权重的方法更本地化,但这可能适合您。

谢谢,但我认为你的解决方案太过复杂了。按照你的回答,我需要在所有的仪表盘活动中添加这段代码,我觉得这样做会显得多余且容易混淆。 - whizzzkey
没问题。顺便说一下,你可以计算一次并将其存储在某个单例类中。 - Dmide

0
在您的res/中创建布局文件夹,并将它们命名为layout、layout-large。现在它们应该适用于不同的屏幕尺寸。

兄弟,我已经创建了这些文件夹,但对我来说毫无用处,因为我在尺寸上拥有所有布局项大小的维度(值-xxxdpi->dimens.xml)。 - whizzzkey

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