图标的Mipmap可绘制对象


449

从Android 4.3(Jelly Bean)开始,我们现在可以使用res/mipmap文件夹来存储“ mipmap”图像。

例如,Chrome for Android将其图标存储在这些文件夹中,而不是更普通的res/drawable文件夹中。

这些mipmap图像与其他熟悉的可绘制图像有何不同?

我在清单中看到,我们使用@mipmap/限定符而不是@drawable/,这在给定资源文件夹名称的情况下是有意义的:

<activity
    android:name=".MipmapDemp"
    android:icon="@mipmap/ic_launcher" />

参考文献:

采用Android 4.3的API文档具有以下的说:

使用mipmap作为位图或可绘制对象的源是提供高质量图像和各种图像比例的一种简单方法,如果您希望在动画过程中对图像进行比例缩放,则该方法特别有用。

Android 4.2(API级别17)在Bitmap类中添加了对mipmap的支持-当您提供了mipmap源并启用了setHasMipMap()时,Android会在Bitmap中交换mip图像。现在,在Android 4.3中,您还可以通过提供mipmap资源并在位图资源文件中设置android:mipMap属性或调用hasMipMap()来为BitmapDrawable对象启用mipmap。

我看不到任何可以帮助我理解的东西。


XML位图资源具有一个android:mipMap属性:

布尔值。启用或禁用mipmap提示。有关更多信息,请参见setHasMipMap()。默认值为false。

据我所知,这不适用于启动器图标。


这个问题是在Google网上论坛上提出的(资源名称“ mipmap”的目的是?!),罗曼·盖伊回答说:

提供通常可以计算的较大分辨率的图像很有用(例如,在mdpi设备上,启动器可能希望较大的hdpi图标显示较大的应用程序快捷方式。)

我觉得这几乎是有道理的,但并非完全如此。

我仍然倾向于Randy Sugianto的后续行动:

这有什么好处?有没有指南如何使用mipmaps,可能是为了更好的启动器图标?


当然,Wikipedia上有一个“ Mipmap”页面,它引用的是1983年发明的一种较旧的技术,我不太了解当前的Android实现。


这些天我们是否应该将所有应用程序图标res/mipmap存储文件夹中,这些mipmap图像的准则是什么?


更新#1

这是一篇博客文章,试图对此进行一些解释。

但是该博客文章中使用的图像显示了看起来像一个文件的文件,其中包含许多徽标。这不是我在Chrome的mipmap文件夹中看到的内容。

Chrome的mipmap-hdpi文件夹包含三张图片。其中之一就是Chrome徽标。

Chrome mipmap-hdpi icon.png

奇怪的是,我希望看到的是72x72,而不是48x48。

也许这就是全部-我们只需要在mipmap文件夹中保留较大的图标?


更新#2

2014年10月23日的Android开发者博客文章再次确认了使用mipmap文件夹作为应用程序图标的想法:

在谈到Nexus 6屏幕密度时,作者写道:

最佳实践是将应用程序图标放置在mipmap-文件夹(而不是drawable-文件夹)中,因为它们的使用分辨率与设备的当前密度不同。例如,可以在启动器上为xxhdpi设备使用xxxhdpi应用程序图标。


更新#3

请注意,Android Studio ic_launcher.pngmipmap...文件夹中而非在drawable...Eclipse用于创建图标的文件夹中创建图标。


Answers:


260

mipmap有两种不同的用法:

  1. 用于构建密度特定的APK时的启动器图标。一些开发人员针对每种密度构建单独的APK,以减小APK的大小。但是,某些启动器(某些设备附带或在Play商店中可用)使用的图标尺寸大于标准48dp。启动器使用getDrawableForDensity并根据需要缩小而不是放大,因此图标是高质量的。例如,在hdpi平板电脑上,启动器可能会加载xhdpi图标。通过将启动器图标放置在mipmap-xhdpi目录中,将不会在构建适用于hdpi设备的APK时像drawable-xhdpi目录那样被剥离。如果您要为所有设备构建一个APK,那么这实际上并不重要,因为启动器可以以所需的密度访问可绘制资源。

  2. 从4.3开始的实际mipmap API。我没有用过,也不熟悉。Android开源项目启动器未使用它,并且我不知道有任何其他启动器在使用。


2
因此,如果我正确理解,那么建议您使用一个构建脚本,为除mipmap资源之外的所有资源剥离不正确的密度文件夹?
理查德·勒·马修里尔

20
我建议只为所有密度构建一个APK,不要担心。但是,是的,有时将mipmap目录用于启动器图标的原因是因为生成脚本(aapt --preferred-configurations)剥离了drawable- {density}目录,而不是mipmap- {density}目录。这似乎似乎是在利用一个漏洞,但是您对Romain Guy和Diane Hackborn在post.plus.google.com/105051985738280261832/posts/QTA9McYan1L上的引用表明,这是设计使然
Kevin TeslaCoil

3
因此,删除mipmap,将图标放置在可绘制对象中以及构建单个APK的典型过程非常完美。听起来mipmap对于我们大多数开发人员而言都是非典型的,但它对我们所有人都具有强制性。
某处某人2015年

在文档中说:“ mipmap:不同启动器图标密度的可绘制文件。” developer.android.com/guide/topics/resources/...
活动

79

似乎所有这些答案以来Google都更新了他们的文档,因此希望这对以后的人们有所帮助:)我自己遇到了这个问题,同时创建了一个新的(新的)项目。

TL; DR:可绘图对象可以作为dp特定资源优化的一部分而删除。Mipmap不会被剥离。

不同设备上的不同主屏幕启动器应用程序会以各种分辨率显示应用程序启动器图标。当应用程序资源优化技术删除了未使用的屏幕密度的资源时,启动器图标看起来会变得模糊,因为启动器应用程序必须将较低分辨率的图标放大才能显示。为避免这些显示问题,应用程序应将mipmap/资源文件夹用于启动器图标。Android系统会保留这些资源,而不考虑密度剥离,并确保启动器应用程序可以选择分辨率最高的图标进行显示。

(来自http://developer.android.com/tools/projects/index.html#mipmap


2
这与导入Studio图像资源时Android Studio的默认位置一致。启动器图标进入mipmap;其他进入可绘制。
爱德华·布雷

2
文档似乎再次发生了变化,developer.android.com / tools / projects / index.html中似乎不存在mipmap (尽管Android文档的其他部分仍在尝试引用它)。
SomeoneElse

28

这些mipmap图像与其他熟悉的可绘制图像有何不同?

这是我的两分钱,试图解释这种差异。在Android中处理图片时,有两种情况需要处理:

  1. 您想根据设备密度加载图像,然后按原样使用它,而不更改其实际大小。在这种情况下,您应该使用可绘制对象,Android会为您提供最合适的图像。

  2. 您想为设备密度加载图像,但是该图像将按比例放大或缩小。例如,当您想要显示更大的启动器图标,或者您有动画会增加图像的大小时,需要使用此图标。在这种情况下,为确保最佳图像质量,应将图像放入mipmap文件夹。Android将要做的是,它将尝试从更高密度的存储桶中拾取图像,而不是放大图像。这将提高图像的清晰度(质量)。

因此,决定将图像放置在何处的经验法则是:

  • 启动器图标始终进入mipmap文件夹。
  • 经常按比例放大(或极度按比例缩小)且其质量对应用程序至关重要的图像也进入了mipmap文件夹。
  • 所有其他图像都是常用的可绘制对象

因此,用于操作栏的图标或用于浮动按钮的图标可以在mipmap中使用?
Juan De la Cruz

不,它们是通常的可绘制对象。
sergej shafarenka,

23

4.3中的mipmaps的Android实现正是Wikipedia文章中解释的1983年的技术:)

mipmap集合的每个位图图像都是主纹理的缩小副本,但是细节有所降低。尽管当视图足以完整渲染细节时仍将使用主纹理,但从远处或以较小的尺寸查看纹理时,渲染器将切换到合适的mipmap图像(...)。

尽管这被描述为3D图形技术(因为它提到“从远处观看”),但它同样适用于2D(翻译为“绘制的是较小的空间”,即“缩小”)。

对于一个具体的Android示例,假设您有一个带有特定背景可绘制背景的View(尤其是 BitmapDrawable)。现在,您可以使用动画将其缩放到其原始大小的0.15。通常,这将需要缩小每帧的背景位图。但是,这种“极端”的缩小可能会产生视觉伪像。

但是,您可以提供一个mipmap,这意味着该图像已经针对某些特定比例(例如1.0、0.5和0.25)进行了预渲染。每当动画“越过” 0.5阈值时,它不会继续缩小原始的1.0尺寸图像,而是切换到0.5图像并将其缩小,这将提供更好的结果。随着动画的继续等等。

这有点理论化,因为它实际上是由渲染器完成的。根据Bitmap类的来源,这只是一个提示,渲染器可能会或可能不会接受它。

/**
 * Set a hint for the renderer responsible for drawing this bitmap
 * indicating that it should attempt to use mipmaps when this bitmap
 * is drawn scaled down.
 *
 * If you know that you are going to draw this bitmap at less than
 * 50% of its original size, you may be able to obtain a higher
 * quality by turning this property on.
 * 
 * Note that if the renderer respects this hint it might have to
 * allocate extra memory to hold the mipmap levels for this bitmap.
 *
 * This property is only a suggestion that can be ignored by the
 * renderer. It is not guaranteed to have any effect.
 *
 * @param hasMipMap indicates whether the renderer should attempt
 *                  to use mipmaps
 *
 * @see #hasMipMap()
 */
public final void setHasMipMap(boolean hasMipMap) {
    nativeSetHasMipMap(mNativeBitmap, hasMipMap);
}

我不太确定为什么这会特别适合应用程序图标。尽管平板电脑上的Android以及某些启动器(例如GEL)要求图标“密度增加一个”来显示更大,但这应该使用常规机制(即drawable-xxxhdpi&c)来完成。


这并不能真正解释与drawable包含mipmapped图像的文件夹的区别。
Timmmm 2015年

2
实际上,这个答案是完全错误的。该唯一的区别是文件是否被剥离或不-它没有任何关系,无论是否纹理映射使用(这是在两种情况下)。该文件夹命名不正确;他们可能应该打电话给它drawable-nostrip
Timmmm 2015年

2
关于mipmap的解释很好,但是Kazuaki提到Google文档条目的答案似乎暗示着这实际上不是原因。
Trilarion 2015年

11

我在另一个线程中提到的一件事值得指出-如果您针对不同的密度构建不同版本的应用程序,则应该了解“ mipmap”资源目录。这与“可绘制”资源完全一样,只是在创建不同的apk目标时不参与密度剥离。

https://plus.google.com/105051985738280261832/posts/QTA9McYan1L


……的确如此,正如凯文在接受的答案中提到的那样。这似乎是其背后的主要原因。
理查德·勒·马修里尔

@RichardLeMesurier是的,只是为了简短明了
kreker


2

当针对不同的密度构建单独的apk时,会剥离用于其他密度的可绘制文件夹。这将使图标在使用更高密度启动器图标的设备中显得模糊。由于不会剥离mipmap文件夹,因此始终最好使用它们来包含启动器图标。


2

在Android中处理图片时,有两种情况需要处理:

  1. 您想按设备密度加载图像,然后按原样使用它,而不更改其实际大小。在这种情况下,您应该使用可绘制对象,Android会为您提供最合适的图像。
  2. 您希望根据设备密度加载图像,但是该图像将按比例放大或缩小。例如,当您想要显示更大的启动器图标,或者您有动画会增加图像的大小时,需要使用此图标。在这种情况下,为确保最佳图像质量,应将图像放入mipmap文件夹。Android将要做的是,它将尝试从更高密度的存储桶中拾取图像,而不是放大图像。

所以

因此,决定将图像放置在何处的经验法则是:

  1. 启动器图标始终进入mipmap文件夹。

  2. 经常按比例放大(或极度按比例缩小)且其质量对应用程序至关重要的图像也进入了mipmap文件夹。

  3. 所有其他图像都是常用的可绘制对象。

引文从这个文章。


1
res/
mipmap-mdpi/ic_launcher.png (48x48 pixels)
mipmap-hdpi/ic_launcher.png (72x72)
mipmap-xhdpi/ic_launcher.png (96x96)
mipmap-xxhdpi/ic_launcher.png (144x144)
mipmap-xxxhdpi/ic_launcher.png (192x192)

启动器的MipMap for app图标

http://android-developers.blogspot.co.uk/2014/10/getting-your-apps-ready-for-nexus-6-and.html

https://androidbycode.wordpress.com/2015/02/14/goodbye-launcher-drawables-hello-mipmaps/


感谢第二篇博客文章!它很好地阐明了drawable-XXXmipmap-XXX文件夹之间的区别:启动器图标与其他资源不同,因为用户启动器中可能会显示更高分辨率的图标。如果已从drawables文件夹中删除了该较高分辨率的图像,则将以编程方式放大一个较低密度的图标。这可能会导致图标没有吸引力。
winklerrr

至少在Nexus P6上的Android 8.1中,drawables文件夹中的启动图标没有放大。实际上根本找不到,并且该应用在打开时崩溃。
马修

1

如果您为目标屏幕分辨率(例如HDPI)构建APK,则Android资产打包工具AAPT可以去除可绘制对象以获得不需要的其他分辨率。但是,如果该文件位于mipmap文件夹中,则这些资产将保留在APK,无论目标分辨率如何。


-1

我对mipmap的了解或多或少是这样的:

当需要绘制图像时,考虑到我们具有不同的屏幕尺寸和分辨率,则必须进行一些缩放。

如果您拥有适合低端手机的图像,则将其缩放到10英寸平板电脑的大小时,必须“发明”实际上不存在的像素。这可以通过一些插值算法来完成。需要发明的像素数量越多,过程所需的时间就越长,质量就会开始下降;使用更复杂的算法所花费的时间越长(例如,周围像素的平均值与复制最近的像素),可以获得最佳质量。

为了减少必须发明的像素数量,使用mipmap可以为同一图像提供不同的大小/分辨率,并且系统将选择最接近要渲染的分辨率的图像并从此处进行缩放。这应该减少发明像素的数量,节省用于计算这些像素以提供高质量图像的资源。

我在一篇文章中对此进行了解释,该文章解释了缩放图像时libgdx中的性能问题:

http://www.badlogicgames.com/wordpress/?p=1403

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.