繁体   English   中英

android:scaleType =“ center”不能满足我的要求:dp vs px如何工作?

[英]android:scaleType=“center” doesn't do what I think it should: how does dp vs px work?

我正在尝试完成必须可以想象的最简单的事情。 我有菜单的背景图片。 我希望在屏幕上显示尽可能多的图像,每个像素一个像素,并且没有缩放比例。

据我所知,这正是scaleType =“ center”应该完成的工作。 不幸的是,无论我做什么,它都拒绝做我想要的事情,而只显示图像的一小部分。

为了用实数阐明,我在sw320dp drawables文件夹中有一个720x1280px的背景图片,由我的sw320dp布局调用。 对于介于320x480px和720x1280px之间的任何屏幕尺寸,他们应该调用该布局并显示该背景图像的一部分。 因此,480x800px的Nexus One应该显示图像的480x800px的一部分。 为此,我有:

<ImageView
android:id="@+id/menuBackground"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
app:srcCompat="@drawable/menubackground_w720" />

不幸的是,它不起作用。 取而代之的是,它仅显示图像的一小部分,大约等于320x480px,长宽比为正负。

经过很多的咒骂和扯掉头发之后,我将可能性缩小为三种合理的理论:

  1. 我正在以一种愚蠢的方式做着非常,非常,非常简单的错误。
  2. 我从根本上不了解dp的工作原理以及可扩展的布局。
  3. 这个世界是一场奇幻的,非理性的洛夫克拉夫特式的噩梦,其中没有任何意义,我注定永远在无望的疯狂圈子中追逐自己的尾巴。

假设第三个选项(即使为true)是“无法解决的”,那么如果有人可以告诉我这是一个还是两个选项,并将我链接到适当的最新资源,我将不胜感激。 感谢您的协助!

tl; dr

我希望在屏幕上显示尽可能多的图像,每个像素一个像素,并且没有缩放比例。

将图像移到res/drawable-nodpi/目录。


经过很多的咒骂和扯掉头发之后,我将可能性缩小为三种合理的理论:

  1. 我正在以一种愚蠢的方式做着非常,非常,非常简单的错误。
  2. 我从根本上不了解dp的工作原理以及可扩展的布局。
  3. 这个世界是一场奇幻的,非理性的洛夫克拉夫特式的噩梦,其中没有任何意义,我注定永远在无望的疯狂圈子中追逐自己的尾巴。

我认为#2可能是最接近真相的。 没关系; 情况很复杂。

让我们开始考虑以下图像:

在此处输入图片说明

我在这里对其进行了调整,以使其在回答中不会占用大量空间,但是在我的计算机上为1000x1000像素。 每个黑色或白色正方形均为100x100像素。 这将使我们很容易推断出应用程序中发生了什么。

接下来,我制作了一个非常简单的应用程序:它只显示200x200 dp的ImageView,而没有其他显示。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#eee">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:scaleType="center"
        android:src="@drawable/checkerboard"/>

</FrameLayout>

我将checkerboard.png放入res/drawable/目录,然后运行该应用程序。 我的模拟器是Nexus 5X,(根据本网站 )其屏幕分辨率为1080x1920像素。 这是我看到的:

在此处输入图片说明

这导致了一些问题:

为什么200 dp宽的ImageView占据一半的屏幕?

dp单元的明确目的是使视图在不同设备上的物理尺寸大致相同。 这里的挑战之一是不同的设备可能具有不同的显示密度 一台手机可能具有适合于物理英寸的320像素的高分辨率显示屏,而另一部手机可能具有仅适合于物理英寸的120像素的高分辨率显示屏。

Android的基准是160 dpi。 在此密度下,1 dp == 1 px。 如果您的设备具有更高的密度,则1 dp等于大于1 px。 Nexus 5X的密度约为423 dpi,因此在我的布局中每1 dp使用约2.6像素。 因此,在此特定仿真器上,200x200 dp表示大约520x520像素。

但是,为什么我的.png只显示200x200像素的图像?

在不同设备上使事物具有相同物理尺寸的另一个挑战是如何处理图像。 我们仅向系统提供了一个checkerboard.png文件,但我们知道ImageView在不同设备上将具有不同的像素尺寸。 剩下两个选择:

系统无法执行缩放。 如果可以,那么我在Nexus 5X上会看到大约520x520像素的图像,但是仍然在运行Nexus One(252 dpi)的人只能看到大约315x315像素的图像。 整个ImageView的物理尺寸大约相同,但是我们两个人会看到完全不同的图像内容。

或者,系统可以按比例放大图像。 现在,它执行与图像数据本身上dp到px相同的缩放比例。 完成此操作后,Nexus 5X和Nexus One都会看到200x200像素的图像数据。 但是,在Nexus 5X上,缩放伪影会变得更糟,因为系统必须将图像放大得更多才能满足更高的显示密度。

我该怎么解决?

这取决于您的最终目标。 如果您只想提供一个.png文件,并且希望系统不按比例放大文件(即,无论显示密度如何,任何设备上的像素都应为1px,以显示图像的1px),则应移动。 png到res/drawable-nodpi/目录

https://developer.android.com/guide/topics/resources/providing-resources.html

nodpi :可用于您不想缩放以匹配设备密度的位图资源。

如果对示例应用程序执行此操作,则在运行它时会看到以下内容:

在此处输入图片说明

确实,我们看到了大约520x520像素的图像。

另一方面,如果您希望每个用户看到相同的物理图像,但又希望避免缩放伪影,则应提供图像文件的多种分辨率

考虑一下从Google的Material Icon存储库下载图标的.png版本时会发生什么情况。 假设我们采用ic_face.png 您将获得一个如下所示的目录结构:

android/
    drawable-mdpi/
        ic_face_black_24dp.png (24x24 pixels)
    drawable-hdpi/
        ic_face_black_24dp.png (36x36 pixels)
    drawable-xhdpi/
        ic_face_black_24dp.png (48x48 pixels)
    drawable-xxhdpi/
        ic_face_black_24dp.png (72x72 pixels)
    drawable-xxxhdpi/
        ic_face_black_24dp.png (96x96 pixels)

这是在以不同的分辨率提供相同图像的不同版本。 具有高显示密度的设备将拍摄与其密度最接近的图像,然后仅将其缩放到很小的数量。 这大大减少了缩放伪影。

进一步阅读

https://developer.android.com/guide/topics/resources/providing-resources.html

https://developer.android.com/guide/practices/screens_support.html

尝试使用

android:scaleType="centerCrop"

我在imageviews上遇到了同样的问题,这每次都解决了我的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM