简体   繁体   English

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

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

I am attempting to accomplish what must surely be the simplest thing imaginable. 我正在尝试完成必须可以想象的最简单的事情。 I have a background image for a menu. 我有菜单的背景图片。 I wish to display as much of that image as fits on the screen, at one pixel per pixel, with no scaling. 我希望在屏幕上显示尽可能多的图像,每个像素一个像素,并且没有缩放比例。

As far as I can tell, this is exactly what scaleType="center" is supposed to accomplish. 据我所知,这正是scaleType =“ center”应该完成的工作。 Unfortunately, no matter what I do, it refuses to do what I want, and instead only shows a small portion of the image. 不幸的是,无论我做什么,它都拒绝做我想要的事情,而只显示图像的一小部分。

To clarify with real numbers, I have a 720x1280px background image in the sw320dp drawables folder, being called by my sw320dp layout. 为了用实数阐明,我在sw320dp drawables文件夹中有一个720x1280px的背景图片,由我的sw320dp布局调用。 For any screensize between 320x480px and 720x1280px, they should call that layout and display a portion of that background image. 对于介于320x480px和720x1280px之间的任何屏幕尺寸,他们应该调用该布局并显示该背景图像的一部分。 So, a 480x800px Nexus One should display a 480x800px portion of the image. 因此,480x800px的Nexus One应该显示图像的480x800px的一部分。 To try and do this, I have: 为此,我有:

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

Unfortunately, it doesn't work. 不幸的是,它不起作用。 Instead, it just displays a very small portion of the image, roughly equal to 320x480px plus or minus a little bit for aspect ratio. 取而代之的是,它仅显示图像的一小部分,大约等于320x480px,长宽比为正负。

After much swearing and tearing my hair out, I have narrowed the possibilities down to three plausible theories: 经过很多的咒骂和扯掉头发之后,我将可能性缩小为三种合理的理论:

  1. I'm doing something really, really, unbelievably simple wrong in a stupid way. 我正在以一种愚蠢的方式做着非常,非常,非常简单的错误。
  2. I fundamentally don't understand how dp works, as well as scalable layouts. 我从根本上不了解dp的工作原理以及可扩展的布局。
  3. The world is a bizarre, irrational Lovecraftian nightmare in which nothing makes any sense and I am doomed to forever chase my own tail in hopeless circles of madness. 这个世界是一场奇幻的,非理性的洛夫克拉夫特式的噩梦,其中没有任何意义,我注定永远在无望的疯狂圈子中追逐自己的尾巴。

Assuming that the third option, even if true, is a "won't fix", I'd appreciate if someone could tell me whether it's option one or two, and link me to an appropriate up-to-date resource. 假设第三个选项(即使为true)是“无法解决的”,那么如果有人可以告诉我这是一个还是两个选项,并将我链接到适当的最新资源,我将不胜感激。 Thanks for any assistance! 感谢您的协助!

tl;dr tl; dr

I wish to display as much of that image as fits on the screen, at one pixel per pixel, with no scaling. 我希望在屏幕上显示尽可能多的图像,每个像素一个像素,并且没有缩放比例。

Move your image into the res/drawable-nodpi/ directory. 将图像移到res/drawable-nodpi/目录。


After much swearing and tearing my hair out, I have narrowed the possibilities down to three plausible theories: 经过很多的咒骂和扯掉头发之后,我将可能性缩小为三种合理的理论:

  1. I'm doing something really, really, unbelievably simple wrong in a stupid way. 我正在以一种愚蠢的方式做着非常,非常,非常简单的错误。
  2. I fundamentally don't understand how dp works, as well as scalable layouts. 我从根本上不了解dp的工作原理以及可扩展的布局。
  3. The world is a bizarre, irrational Lovecraftian nightmare in which nothing makes any sense and I am doomed to forever chase my own tail in hopeless circles of madness. 这个世界是一场奇幻的,非理性的洛夫克拉夫特式的噩梦,其中没有任何意义,我注定永远在无望的疯狂圈子中追逐自己的尾巴。

I think #2 is probably the closest to the truth. 我认为#2可能是最接近真相的。 That's okay; 没关系; it's complicated. 情况很复杂。

Let's start by considering this image: 让我们开始考虑以下图像:

在此处输入图片说明

I've resized it here so that it doesn't take up a ton of space in my answer, but on my computer it is 1000x1000 pixels. 我在这里对其进行了调整,以使其在回答中不会占用大量空间,但是在我的计算机上为1000x1000像素。 Each black or white square is 100x100 pixels. 每个黑色或白色正方形均为100x100像素。 That will make it really easy to reason about what's going on in our application. 这将使我们很容易推断出应用程序中发生了什么。

Next, I make an app that's dead simple: it just displays a 200x200 dp ImageView, and nothing else. 接下来,我制作了一个非常简单的应用程序:它只显示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>

I put my checkerboard.png into the res/drawable/ directory, and I run the app. 我将checkerboard.png放入res/drawable/目录,然后运行该应用程序。 My emulator is a Nexus 5X, which (according to this site ) has a screen resolution of 1080x1920 pixels. 我的模拟器是Nexus 5X,(根据本网站 )其屏幕分辨率为1080x1920像素。 This is what I see: 这是我看到的:

在此处输入图片说明

Huh. That leads to some questions: 这导致了一些问题:

Why is my 200 dp wide ImageView taking up half the screen? 为什么200 dp宽的ImageView占据一半的屏幕?

The express purpose of the dp unit is to allow Views to be approximately the same physical size across different devices. dp单元的明确目的是使视图在不同设备上的物理尺寸大致相同。 One challenge here is that different devices can have different display densities ; 这里的挑战之一是不同的设备可能具有不同的显示密度 one phone might have a high-res display that fits 320 pixels into a physical inch while another might have a low-res display that only fits 120 pixels into a physical inch. 一台手机可能具有适合于物理英寸的320像素的高分辨率显示屏,而另一部手机可能具有仅适合于物理英寸的120像素的高分辨率显示屏。

The baseline for Android is 160 dpi. Android的基准是160 dpi。 At this density, 1 dp == 1 px. 在此密度下,1 dp == 1 px。 If your device has a higher density, 1 dp will equal more than 1 px. 如果您的设备具有更高的密度,则1 dp等于大于1 px。 The Nexus 5X has a density of ~423 dpi, so it uses about 2.6 pixels for each 1 dp in my layouts. Nexus 5X的密度约为423 dpi,因此在我的布局中每1 dp使用约2.6像素。 So, on this specific emulator, 200x200 dp means approximately 520x520 px. 因此,在此特定仿真器上,200x200 dp表示大约520x520像素。

But why is my .png only showing 200x200 pixels worth of image? 但是,为什么我的.png只显示200x200像素的图像?

Another challenge in making things the same physical size on different devices is how to deal with images. 在不同设备上使事物具有相同物理尺寸的另一个挑战是如何处理图像。 We've provided the system only a single checkerboard.png file, but we know that our ImageView is going to have different pixel dimensions on different devices. 我们仅向系统提供了一个checkerboard.png文件,但我们知道ImageView在不同设备上将具有不同的像素尺寸。 That leaves two options: 剩下两个选择:

The system could perform no scaling. 系统无法执行缩放。 If it did, then I'd see about 520x520 pixels worth of image on my Nexus 5X, but someone still running a Nexus One (252 dpi) would only see about 315x315 pixels worth of image. 如果可以,那么我在Nexus 5X上会看到大约520x520像素的图像,但是仍然在运行Nexus One(252 dpi)的人只能看到大约315x315像素的图像。 The overall ImageView would be about the same physical size, but the two of us would see wildly different image content. 整个ImageView的物理尺寸大约相同,但是我们两个人会看到完全不同的图像内容。

Or, the system can scale the image up. 或者,系统可以按比例放大图像。 Now it performs the same scaling we talked about for dp to px on the image data itself. 现在,它执行与图像数据本身上dp到px相同的缩放比例。 Having done that, both the Nexus 5X and the Nexus One will see 200x200 pixels worth of image data. 完成此操作后,Nexus 5X和Nexus One都会看到200x200像素的图像数据。 However, the scaling artifacts will be worse on the Nexus 5X, since the system has to scale the image up more to satisfy the higher display density. 但是,在Nexus 5X上,缩放伪影会变得更糟,因为系统必须将图像放大得更多才能满足更高的显示密度。

What should I do to fix it? 我该怎么解决?

That depends on what your end goal is. 这取决于您的最终目标。 If you want to provide only a single .png file, and you want the system to not scale it up (ie you want 1px on any device, regardless of display density, to display 1px of your image), then you should move the .png to the res/drawable-nodpi/ directory . 如果您只想提供一个.png文件,并且希望系统不按比例放大文件(即,无论显示密度如何,任何设备上的像素都应为1px,以显示图像的1px),则应移动。 png到res/drawable-nodpi/目录

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

nodpi : This can be used for bitmap resources that you don't want to be scaled to match the device density. nodpi :可用于您不想缩放以匹配设备密度的位图资源。

If we do this for our sample app, we see this when we run it: 如果对示例应用程序执行此操作,则在运行它时会看到以下内容:

在此处输入图片说明

Indeed, we see about 520x520 pixels worth of image. 确实,我们看到了大约520x520像素的图像。

If, on the other hand, you want every user to see the same physical image, but you want to avoid scaling artifacts, then you should provide multiple resolutions of your image file . 另一方面,如果您希望每个用户看到相同的物理图像,但又希望避免缩放伪影,则应提供图像文件的多种分辨率

Consider what happens when you download the .png version of an icon from Google's Material Icon repo. 考虑一下从Google的Material Icon存储库下载图标的.png版本时会发生什么情况。 Let's say we take ic_face.png . 假设我们采用ic_face.png You get a directory structure that looks like this: 您将获得一个如下所示的目录结构:

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)

What this is doing is giving different versions of the same image at different resolutions. 这是在以不同的分辨率提供相同图像的不同版本。 Devices with a high display density will take the image that most closely matches their density, and then only scale it a very small amount. 具有高显示密度的设备将拍摄与其密度最接近的图像,然后仅将其缩放到很小的数量。 This reduces the scaling artifacts dramatically. 这大大减少了缩放伪影。

Further reading 进一步阅读

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

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

Try using 尝试使用

android:scaleType="centerCrop"

I've been having same issue with imageviews and this solved my problem everytime. 我在imageviews上遇到了同样的问题,这每次都解决了我的问题。

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

相关问题 Java:replaceAll不起作用,我认为应该 - Java: replaceAll doesn't work as I think it should Google Maps不能在所有设备上使用,而不能在其他设备上使用。我该怎么办? - Google Maps doesn't work on all devices while on other does.What should I do? 在 Android 应用程序中,我将所有 px 更改为 dp 和 sp。 现在打不开了。 怎么了? - In Android app,I changed all px to dp and sp. Now it is not opening. What is wrong? 为什么我的线程没有像我认为的那样做?(Android internet over main thread问题) - Why does my thread not do what i think it does?(Android internet over main thread issue) android中px和dp之间的不一致 - Inconsistency between px and dp in android 我需要 java 的工作输入。 扫描仪不起作用,因此也没有缓冲区。 关于我应该怎么做 - i need working input for java. scanner doesn't work so neither buffer. on idea what should i do 为什么1dp在Android上同时表示3px和2px? - Why does 1dp mean 3px and 2px at the same time on Android? “ android:padding = -5dp”是什么意思? - what does “android:padding=-5dp” mean? 对象没有返回我认为应该的状态 - Objects not returning what I think it should be 我认为应该显示Android AlertDialog时未显示 - Android alertdialog not showing when I think it should
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM