两个屏幕,大小相同但密度不同

9

两个屏幕,除了密度不同外,几乎相同大小:

左侧屏幕是模拟器 768x1280 160dpi (MDPI)。 右侧屏幕是模拟器 720x1280 320dpi (XHDPI)。

enter image description here

我使用宽度 300dp 和高度 300dp。 XML:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/picture"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:src="@drawable/picture"
        android:layout_centerInParent="true"/>
</RelativeLayout>

无论清晰度/图像质量如何,两个图像在两个(或其他)屏幕上都应填充相同的空间吗?这里有一个确认这种说法的答案:链接 编辑:我看到有用户说必须为不同的屏幕复制相同的XML,以便可以更改元素的DP值。如果这是真的,我认为我误解了DP单位的目的。我认为它旨在使用相同的DP值使图像在不同的屏幕上具有完全相同的大小。你能澄清一下吗?

2
请问,您是否检查过项目的drawable文件夹(mdpi和xhdpi)中是否有不同尺寸的图像? - statosdotcom
是的。目前,我只有一个测试用的图像版本。 但是我已经包含了所有的桶进行测试,但仍然没有运气。 - AndroidDev
3个回答

15

我认为使用模拟器导致了有些混淆。

像你在这里所做的一样指定dp单位,应该意味着图像在不同设备上的物理尺寸大致相同。在你的问题中,你说我们正在比较两个几乎相同大小的屏幕,但事实并非如此!

根据您在问题中陈述的分辨率,我们实际上正在查看(大约)左侧的9英寸平板电脑和右侧的4.5英寸手机。由于这些是虚拟设备,可以在屏幕上调整大小,它们可以被制作成外观相同的大小,但实际上它们代表着非常不同的东西。

在左侧,我们可以从状态栏和系统按钮中看到,这确实看起来像一个平板电脑,并且我已经在状态栏中使用图标作为粗略的测量标准:

enter image description here

这证实了一个期望:如果你真的有一个平板电脑和一个手机在你面前(或者模拟器的比例是正确的),那么这个图像在两个设备上的物理大小将是相同的。

编辑-针对此答案中的评论提供更多细节:

描述dp尺寸的目的是它们在具有不同像素密度的设备上将是相同的物理大小。这就是你以上所做的。例如,如果该元素每边都是2英寸,那么它在高分辨率或低分辨率电话上都是2英寸,在高分辨率或低分辨率平板电脑上也是2英寸。

如果您想要的不是元素实际上相同的大小,而是始终占屏幕的相同比例(比如总是占屏幕宽度的90%),则可以选择几种类型的布局。

LinearLayout使用权重的概念来分配不同比例的空间。

支持库包含 PercentRelativeLayoutPercentFrameLayout,它们类似于普通布局,但可以使用百分比指定大小。

新的ConstraintLayout目前仅在Android Studio 2.2预览版中提供。我自己还没有使用过它,但似乎它包括自己的比例和基于百分比的概念,也能实现这个功能。


2
那我不能指望在所有屏幕上使用相同的DP值。我必须为每个屏幕尺寸创建不同的XML文件吗? - AndroidDev
你想要实现什么目标? - Lewis McGeary
将我的应用程序按比例在不同的设备上运行。 - AndroidDev
我已经编辑了上面的答案,以阐述使用dp来实现一致的物理尺寸和使用其他技术来实现屏幕比例一致性之间的区别。 - Lewis McGeary
1
谢谢,Lewis。我想百分比相对布局是我需要的。 - AndroidDev

2

您也可以在编程中实现此功能,因此针对不同的屏幕尺寸(也适用于不同的密度),您可以通过获取屏幕尺寸然后计算所需宽度和高度的像素数量(以百分比表示)来设置图像大小。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout_xml);

    DisplayMetrics metrics = getResources().getDisplayMetrics();
    int screenWidthInPixels = metrics.widthPixels;
    int screenHeightInPixels = metrics.heightPixels;

    int imageWidth = Math.round (screenWidthInPixels * (58.57/100)); //58.57 is the percentage value for image width
    int imageHeight = Math.round (screenHeightInPixels * (58.57/100)); //58.57 is the percentage value for image height

    ImageView picture= (ImageView)findViewById(R.id.your_image_id);
    picture.setLayoutParams(new RelativeLayout.LayoutParams((int) imageWidth , (int) imageHeight ));


    }

0

简单澄清:

第一个屏幕,密度为160 [MDPI]:

在这里,1 dp[你在xml的ImageView宽度中使用] = 1像素[px]。这是Android规定的。 因此,图像在宽度和高度上都显示为完整的300像素。

第二个屏幕,密度为320 [XHDPI]:

在这里,1 dp[你在xml的ImageView宽度中使用] = 2像素[px]。

而且,由于你在宽度和高度中使用了“300dp”,这意味着你要求Android使用“密度像素”[dp]而不是物理像素[px]。

因此,300 dp = 600像素[px]

这就是为什么第二个模拟器中的ImageView大小是原来的两倍。

希望这能解决疑惑。

解决方案:

如果你想让你的ImageView宽度和高度相同,那么你可以在android:width和android:height中使用android:weight属性。这将在你的imageview两侧分配相等的空间。

运行时查找密度的示例代码:

private static String getDensityName(Context context){
    float density = getResources().getDisplayMetrics().density;

    if(density >= 4.0){
        return “xxxhdpi”;
    }
    if(density >= 3.0){
        return “xxhdpi”;
    }
    if(density >= 2.0){
       return “xhdpi”;
    }
    if(density >= 1.5){
       return “hdpi”;
    }
    if(density >= 1){
       return “mdpi”;
    }
    return “ldpi”;

}

嗨,Anish,我理解了你的解释,很有道理。但是我不明白的是“密度无关像素”这个术语。对我来说毫无意义...如果它是独立的,那么在不同密度下使用相同dp值显示相同图像不应该产生不同的结果,对吧? - AndroidDev
1
@LevySchiavetti:你好,实际上,“密度无关像素”这个概念是在“屏幕尺寸相同但像素数量不同”的情况下出现的。在这种情况下,你的代码将正确地在两个屏幕上显示图像。而在你的情况下,则相反。因此,你需要2个图像:1个为mdpi密度,另一个为xhdpi密度。只需将这两个不同的图像放入这些单独的文件夹中,问题就解决了。 - Anish Mittal
尝试查找两个模拟器的密度。并检查它们是否与您上面指定的密度匹配?我在我的上面的回答中放置了查找密度的代码。 - Anish Mittal

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