关于android:图标的Mipmap drawables

Mipmap drawables for icons

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

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

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

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

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

参考文献:

Android 4.3 API文档包含以下内容:

Using a mipmap as the source for your bitmap or drawable is a simple
way to provide a quality image and various image scales, which can be
particularly useful if you expect your image to be scaled during an
animation.

Android 4.2 (API level 17) added support for mipmaps in the Bitmap
class—Android swaps the mip images in your Bitmap when you've supplied
a mipmap source and have enabled setHasMipMap(). Now in Android 4.3,
you can enable mipmaps for a BitmapDrawable object as well, by
providing a mipmap asset and setting the android:mipMap attribute in a
bitmap resource file or by calling hasMipMap().

我没有看到任何有助于我理解的东西。

XML Bitmap资源具有android:mipMap属性:

Boolean. Enables or disables the mipmap hint. See setHasMipMap() for
more information. Default value is false.

就我所见,这不适用于启动器图标。

问题出现在Google网上论坛(资源名称"mipmap"的目的?!)上,Romain Guy回复道:

It's useful to provide an image at a larger resolution that would
normally be computed (for instance, on an mdpi device, Launcher might
want the larger hdpi icon to display large app shortcuts.)

我觉得这几乎是有意义的,但并不完全。

我仍然倾向于选择Randy Sugianto的跟进:

What are the advantages of this? Is there any guide how to use
mipmaps, probably for better launcher icons?

当然,维基百科有一个"Mipmap"页面,它指的是一种1983年发明的旧技术,我无法与当前的Android实现相关联。

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

更新#1

这是一篇博文,试图解释一下。

  • Android 4.3中的drawables的Mipmapping

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

Chrome的mipmap-hdpi文件夹包含三张图片。一个是Chrome徽标,单独使用。

Chrome mipmap-hdpi icon.png

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

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

更新#2

2014年10月23日的Android开发者博客文章再次证实了将mipmap文件夹用于应用程序图标的想法:

  • 让您的应用程序为Nexus 6和Nexus 9做好准备

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

It’s best practice to place your app icons in mipmap- folders (not the
drawable- folders) because they are used at resolutions different from
the device’s current density. For example, an xxxhdpi app icon can be
used on the launcher for an xxhdpi device.

更新#3

请注意,Android Studio会在mipmap...文件夹中创建ic_launcher.png图标,而不是Eclipse用于创建它们的drawable...文件夹。


mipmap有两种不同的用途:

  • 用于构建密度特定APK时的启动器图标。一些开发人员为每个密度构建单独的APK,以保持APK大小。但是,某些发射器(随某些设备一起提供,或在Play商店中提供)使用比标准48dp更大的图标尺寸。启动器使用getDrawableForDensity并在需要时缩小,而不是向上缩小,因此图标质量很高。例如,在hdpi平板电脑上,启动器可能会加载xhdpi图标。通过将启动器图标放在mipmap-xhdpi目录中,在为hdpi设备构建APK时,它不会像drawable-xhdpi目录那样被剥离。如果您正在为所有设备构建单个APK,那么这并不重要,因为启动程序可以访问可绘制资源以获得所需的密度。

  • 4.3的实际mipmap API。我没有使用它,我不熟悉它。它没有被Android开源项目启动器使用,我也不知道有任何其他启动器使用。


  • 似乎谷歌已经更新了他们的文档,因为所有这些答案,所以希望这将在未来帮助其他人:)在创建一个新的(新的)项目时,我自己也遇到过这个问题。

    TL; DR:drawables可以作为dp特定资源优化的一部分被剥离。 Mipmap不会被剥离。

    Different home screen launcher apps on different devices show app launcher icons at various resolutions. When app resource optimization techniques remove resources for unused screen densities, launcher icons can wind up looking fuzzy because the launcher app has to upscale a lower-resolution icon for display. To avoid these display issues, apps should use the mipmap/ resource folders for launcher icons. The Android system preserves these resources regardless of density stripping, and ensures that launcher apps can pick icons with the best resolution for display.

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


    How are these mipmap images different from the other familiar drawable images?

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

  • 您希望为设备密度加载图像,并且您将"按原样"使用它,而不会更改其实际大小。在这种情况下,您应该使用drawables,Android将为您提供最佳的图像。

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

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

    • 启动器图标始终进入mipmap文件夹。
    • 通常按比例放大(或缩小尺寸)且质量对应用程序至关重要的图像也会进入mipmap文件夹。
    • 所有其他图像都是常用的图形。


    4.3中的mipmaps的Android实现正是1983年维基百科文章中解释的技术:)

    Each bitmap image of the mipmap set is a downsized duplicate of the
    main texture, but at a certain reduced level of detail. Although the
    main texture would still be used when the view is sufficient to render
    it in full detail, the renderer will switch to a suitable mipmap image
    (...) when the texture is viewed from a distance or at a small size.

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

    对于一个具体的Android示例,假设您有一个具有特定背景可绘制的视图(特别是BitmapDrawable)。您现在使用动画将其缩放到原始大小的0.15。通常,这需要缩减每帧的背景位图。然而,这种"极端"降尺度可能会产生视觉伪影。

    但是,您可以提供一个mipmap,这意味着图像已经预先渲染了几个特定的??比例(比方说1.0,0.5和0.25)。每当动画"越过"0.5阈值时,不是继续缩小原始的1.0大小的图像,而是切换到0.5图像并缩小它,这应该提供更好的结果。等动画继续进行。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    /**
     * 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,&amp; c)来完成。


    One thing I mentioned in another thread that is worth pointing out -- if you are building different versions of your app for different densities, you should know about the"mipmap" resource directory. This is exactly like"drawable" resources, except it does not participate in density stripping when creating the different apk targets.

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


    由于我正在寻找一个明确的答案,以确定通知图标的正确类型,我想在这个主题中添加这个明确的声明。它来自http://developer.android.com/tools/help/image-asset-studio.html#saving

    Note: Launcher icon files reside in a different location from that of
    other icons. They are located in the mipmap/ folder. All other icon
    files reside in the drawable/ folder of your project.


    There are two cases you deal with when working with images in Android:

  • You want to load an image for your device density and you are going to use it"as is", without changing its actual size. In this case you
    should work with drawables and Android will give you the best fitting
    image.
  • You want to load an image for your device density, but this image is going to be scaled up or down. For instance this is needed when you
    want to show a bigger launcher icon, or you have an animation, which
    increases image’s size. In such cases, to ensure best image quality,
    you should put your image into mipmap folder. What Android will do is,
    it will try to pick up the image from a higher density bucket instead
    of scaling it up.
  • SO

    Thus, the rule of thumb to decide where to put your image into would
    be:

  • Launcher icons always go into mipmap folder.

  • Images, which are often scaled up (or extremely scaled down) and whose quality is critical for the app, go into mipmap folder as
    well.

  • All other images are usual drawables.

  • 引用本文。


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


    如果您为目标屏幕分辨率(如HDPI)构建APK,则Android资产打包工具AAPT可以删除您不需要的其他分辨率的drawable。但如果它位于mipmap文件夹中,那么这些资产将保留在APK,无论目标分辨率如何。


    1
    2
    3
    4
    5
    6
    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

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

    Goodbye launcher drawables, hello mipmaps!


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

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

    如果您的图像适用于低端手机,当您将其缩放到10英寸平板电脑的大小时,您必须"发明"实际上不存在的像素。这是通过一些插值算法完成的。必须发明的像素数量越多,过程所需的时间越长,质量开始失败。使用更复杂的算法需要更长的时间(周围像素的平均值与复制最近的像素)获得最佳质量。

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

    我在一篇文章中解释了这一点,解释了在缩放图像时libgdx中的性能问题:

    Know Your Texture Filters!