非常经典的Android开发问题-mipmap图标目录和drawable图标目录的区别和适用场景实战举例-优雅草卓伊凡

非常经典的Android开发问题-mipmap图标目录和drawable图标目录的区别和适用场景实战举例-优雅草卓伊凡

核心结论(先看这个)

  • 对于应用图标(App Icon) :永远放在 mipmap 目录中。
  • 对于其他所有图标和图片资源 :如图标按钮、标签页图标、背景图、占位图等,都放在 drawable 目录中。

这是Google自Android Studio 1.0版本后官方推荐的最佳实践。


详细区别与适用场景

1. mipmap 目录

  • 设计初衷 :专门为应用启动器图标(Launcher Icon) 设计。
  • 关键特性系统永远不会对 ****mipmap ****目录下的资源进行缩放 。无论你的应用安装在哪一种屏幕密度的设备上,Launcher(桌面)都会获取到为该设备分辨率精确匹配的 mipmap 资源,从而确保应用图标始终清晰、无锯齿。
  • 适用场景
    • 有且仅有 :你的应用图标,即 ic_launcheric_launcher_round 等。这些图标会显示在手机桌面、应用列表、设置界面以及分享菜单中。
  • 为什么不放别的 :如果把其他UI图标也放在 mipmap 中,系统不会缩放它们,你在布局中引用时可能需要自己处理尺寸,反而增加麻烦。而且这违背了该目录的设计初衷。

2. drawable 目录

  • 设计初衷 :存放应用内所有其他的图片资源
  • 关键特性 :系统可能会根据设备的屏幕密度(dpi)对 drawable 目录下的图片进行缩放,以适配不同屏幕。系统会选择最接近的密度版本,然后缩放至合适大小。
  • 适用场景除了应用启动图标之外的所有图片。包括但不限于:
    • UI图标(如返回箭头、菜单图标、心形收藏图标等)
    • 按钮背景(Button Backgrounds)
    • 界面背景(Backgrounds)
    • 位图(Bitmaps)
    • XML绘制的形状(Shapes)、选择器(Selectors)等

为什么会有这个区分?------ 历史与优化

在早期Android版本中,所有图片资源都放在 drawable 目录下。但这样做有一个问题:

当设备屏幕密度很高(比如xxhdpi)而你的应用只提供了低密度(比如mdpi)的应用图标时,系统会从 drawable 目录中获取这个低清图标,并放大它来显示在桌面上。放大必然导致图标模糊、失真,用户体验很差。

为了解决这个问题,Android引入了 mipmap 目录。mipmap 一词源自计算机图形学,指的是一组预先生成的、不同精度的纹理图片。系统可以精确地为设备选择最合适的那一个,而无需进行缩放。

因此,将应用图标单独放入 mipmap 目录,确保了桌面Launcher总能拿到最精确尺寸的图标,与设备DPI完美匹配。而应用内部的UI元素因为布局复杂,缩放是不可避免的,所以继续留在 drawable 目录中由系统处理。

目录结构示例

一个标准的项目资源目录结构看起来是这样的:

less 复制代码
src/main/res/
├── drawable/          // 默认drawable目录(通常放xml资源,如selector, shape)
├── drawable-hdpi/     // 为hdpi屏幕准备的png/jpg图片
├── drawable-xhdpi/    // 为xhdpi屏幕准备的png/jpg图片
├── drawable-xxhdpi/   // 为xxhdpi屏幕准备的png/jpg图片
├── mipmap-hdpi/       // 只放应用图标 ic_launcher.png
├── mipmap-xhdpi/      // 只放应用图标 ic_launcher.png
├── mipmap-xxhdpi/     // 只放应用图标 ic_launcher.png
├── mipmap-xxxhdpi/    // 只放应用图标 ic_launcher.png (建议提供,作为高分辨率设备的基准)
├── layout/
└── values/

总结与最佳实践

特性 mipmap****目录 drawable****目录
主要用途 应用启动器图标(App Launcher Icon) 应用内所有其他UI元素和图片
系统缩放 永不缩放,保证图标清晰 会根据设备dpi进行缩放
包含内容 `ic_launcher(.webp .png .xml)` 按钮图标、背景、位图、选择器、形状等
最佳实践 所有密度版本都应提供该图标 为不同密度提供相应的图片以优化性能和效果

记住这个黄金法则:

mipmap ****for the app icon, ****drawable ****for everything else.
(mipmap放应用图标,drawable放其他所有东西。)

实际项目举例

看到这两个图标了没,一个是默认页面的背景图,另一个是被选中按钮激活后的选项背景图

结论先行

这两个资源都属于"应用内其他图片资源",都应该放在 ****drawable ****目录中。

  • 按钮选中状态的背景 -> drawable 目录
  • 主页面整体背景 -> drawable 目录

详细解释

1. 按钮选中状态的背景

这个背景是应用内部UI交互 的一部分。它可能是一个图片(.png, .jpg, .webp),也可能是一个用XML定义的选择器(Selector)形状(Shape)

  • 如果是图片文件 (如 btn_selected_bg.png):
    你应该将它放入对应的密度文件夹中,例如 drawable-xhdpi/, drawable-xxhdpi/ 等。系统会根据设备屏幕密度自动选择最合适的一个,并在需要时进行缩放,以保证在不同设备上显示比例正确。
  • 如果是XML文件 (如 btn_selected_bg.xml,里面可能是 <selector><shape>):
    你应该将它直接放入默认的 ****drawable/ ****目录(不带密度后缀)。因为XML是矢量性的,系统可以根据描述在任何密度下完美地绘制出图形,无需为不同密度提供多个版本。

放置路径示例:

  • res/drawable/btn_selected_bg.xml (XML选择器)
  • res/drawable-xhdpi/btn_selected_bg.png (XHDPI密度图片)
  • res/drawable-xxhdpi/btn_selected_bg.png (XXHDPI密度图片)

2. 主页面整体背景

这个背景同样是应用内部的装饰性图片 ,不属于应用图标。它通常是一张较大的图片(如 bg_home.jpg)。

  • 你应该根据它的尺寸和预期效果,为不同屏幕密度提供优化后的版本,并放入对应的 drawable-dpi 目录中。例如,为高密度设备提供更高分辨率的背景图,可以避免在大屏手机上被拉伸而模糊。

放置路径示例:

  • res/drawable-mdpi/bg_home.jpg (通常不需要,但遵循规范的话应该提供)
  • res/drawable-hdpi/bg_home.jpg
  • res/drawable-xhdpi/bg_home.jpg
  • res/drawable-xxhdpi/bg_home.jpg (这是目前最主流的基准尺寸)

为什么不能放 mipmap

回顾一下 mipmap 的核心特性:系统永不缩放

如果你把主页背景图 bg_home.jpg 放在 mipmap-xxhdpi/ 目录下,然后在一个 hdpi 的设备上运行:

  1. 系统会去 mipmap-hdpi/ 找,但你没提供这个版本。
  2. 系统不会 像处理 drawable 那样自动缩放 mipmap-xxhdpi 里的图来适配。
  3. 它会直接使用 mipmap-xxhdpi/ 里的原图,这张图在 hdpi 设备上会显得非常大,可能超出屏幕,导致显示异常。

把按钮背景放在 mipmap 里也会有类似的问题,因为系统不会帮你做任何缩放适配,你需要自己写代码去控制大小,这完全违背了Android资源适配的初衷。

总结表格

资源类型 推荐目录 原因
应用图标 (ic_launcher) mipmap-*dpi/ 确保桌面启动器获取未缩放的清晰图标
按钮背景 (图片或XML) drawable/drawable-*dpi/ 属于应用内UI,需要系统进行密度适配
页面背景图 drawable-*dpi/ 属于应用内装饰性图片,需要系统进行密度适配
XML选择器/形状 drawable/(无密度后缀) XML可自适应不同密度,一份资源即可

简单记忆:只要不是那个会被手机桌面用到的图标,统统扔进 drawable

相关推荐
小月鸭9 分钟前
如何理解HTML语义化
前端·html
jump68032 分钟前
url输入到网页展示会发生什么?
前端
诸葛韩信36 分钟前
我们需要了解的Web Workers
前端
brzhang41 分钟前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu1 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花1 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋1 小时前
场景模拟:基础路由配置
前端
六月的可乐1 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程
一 乐2 小时前
智慧党建|党务学习|基于SprinBoot+vue的智慧党建学习平台(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·学习
BBB努力学习程序设计3 小时前
CSS Sprite技术:用“雪碧图”提升网站性能的魔法
前端·html