众所周知,Android 的特点之一,在于它为用户提供了相对而言更大的自由度,而这也成了很多智能手机爱好者选择 Android 的理由之一。要知道,对于个性化来说,Android 用户除了更换壁纸铃声,还能更换应用图标、系统配色、字体、主题、桌面小工具......甚至整个桌面启动器。

如此之多的自定义项目,让每台 Android 手机都可以做到「千机千面」,体现属于你自己的个性。

那么,如果你之前研究过如何个性化 Android,你肯定听说过「图标包」这个概念。一般来说,图标包在 Android 上,指的是一些适用于一些第三方启动器的自定义图标集合包,通常作为一个 APK 进行安装。

但这些 Android 图标包毕竟都是公开下载的,动手能力强的朋友们可能觉得还不够个性想自己画一套;也有的看上了别家 ROM 主题中的图标,想在自己的启动器上用......

问题来了,有没有可能自己动手,DIY 一套图标包呢?要是你动了这个念头,恭喜你,本文就是为你准备的。

何为 NanoIconPack

NanoIconPack 是一套简单轻量的图标包模版,由国人 By_syk 开发,并以 Apache 许可证 2.0 版开源,任何人都可以基于这套模版二次开发图标包。

这套模版功能不多,但胜在简洁实用,界面友好,同时兼容性也非常高。除了「老三样」Nova、Apex 和 ADW,它还支持各种其他沿用图标包规范的启动器。

已经有很多图标包是基于 NanoIconPack 二次开发而成,其中包括 PDC 图标包Cardicons Ⅱ 图标包 等。如果你也想自己绘制图标并打包,那么选择在 NanoIconPack 的基础上进行二次开发,是一个非常好的选择。

理论上,二次开发 NanoIconPack 最好是拥有一定的 Android 开发基础;但如果你完全没有接触过编程,也没关系,只要跟着本文中描述的步骤走,胆大心细,你也可以打造出属于自己的一款图标包。

准备图标

既然要做图标包,准备好图标自然是硬性条件。你可以选择自己画一套图标,还可以从其他 ROM(例如 MIUI)的主题文件中提取。

需要注意的是,图标的尺寸虽然没有硬性规定,但最好是 192*192 px,这一数值也是 Android 上 xxxhdpi 分辨率图标的默认大小。更大也不是不可以,但不要太大,否则可能会影响到启动器的正常显示。

图标的命名也有些讲究,开发者 By_syk 在 Wiki 上给出了如下命名规则建议:

  • 图标文件名(不包括 .png 扩展名)仅使用小写字母+数字+下划线([a-z\d_]+)
  • 不能使用数字打头(\D.*)
  • 重名则以下划线加数字添加后缀(_1)
  • 为了避免与上一条重名规则冲突,应用名中的英文与数字之间不要用下划线隔开。例如相机 360 应命名为 camera360而不是 camera_360.png

正确的例子:

cuto.png chrome_dev.png camera_1.png

错误的例子:Calendar.png 500px.png camera_360.png

因为模版的文件中已存在占位符,个人建议将数个常用的系统图标以如下方式命名,以节省一定的工作量:

计算器 - calculator
日历 - calendar
相机 - camera
时钟 - clock
通讯录 - contacts
电子邮件 - email
图库 - gallery
音乐 - music
电话 - phone
设置 - settings
短信 - sms

准备好之后,将它们保存到一个文件夹备用。

本文中将使用提取自 MIUI「凹凸世界」主题文件中的图标为范例。图标原作者:hynick

安装 Android Studio 和 SDK 工具 & 注册 GitHub 账号

为了继续接下来的开发工作,你需要安装一个 Android Studio 以及相应的 SDK 工具包。

前往此处 下载 Android Studio,但请务必注意,在安装过程中可能会遇到需要对网络环境进行处理才能解决的错误,请在网络上查找相应教程进行解决。

本文中将不再赘述相关安装过程。

同时,如果你之前没有 GitHub 账号,你还需要去新注册一个。注册 GitHub 账号很简单,点击 Sign Up 后按提示输入对应信息即可。在此同样不详细讨论了。

将项目导入 Android Studio

万事准备周全后,打开 Android Studio,在右上角找到 File 选项,选择 New → Project from Version Control → GitHub

然后会弹出 Clone Repository 窗口,如图所示,在 URL 处填入 https://github.com/by-syk/NanoIconPack.git (此时可以点击 Test 按钮测试能否正常访问),将 Directory Name 改成自己为图标包起的名字,点击 Clone .

如果之前没有用 GitHub 账号登录过 Android Studio,那此时会提示你登录 GitHub,按提示正常登录后执行上述操作即可。

接下来,你需要耐心等待 Cloning 操作完成。

一旦完成后, Android Studio 便会自动显示项目界面:

界面中左侧显示的是项目的文件夹与文件,其中的 /nanoiconpack 为库代码,/app 为应用代码。下文中的内容,基本上只涉及到对应用代码,也就是 /app 目录的修改。

添加图标

该往模版里添加图标了。找到 /app 下的 /res/drawable 目录,右键点击,选择「Show in Explorer」选项,此时应该会显示 res 文件夹,双击打开 drawable-nodpi :

此时将里面的文件全部删除,再将之前准备好的图标拷贝进去。

如果你还准备了 384*384 px 的大尺寸图标样本,你可以回到上一级目录中,将那些图标拷贝到 mipmap-nodpi 文件夹中,这样会让图标包应用中自动显示高清图标。但这些图标仅用于展示,不会应用于启动器。

接下来,在 Android Studio 中找到 /res/drawable/values 下的 icon_pack.xml,这其中包含了两个 icon_pack.xml 文件,有一个带有中国国旗图标,作为简体中文本地化的版本。

这个文件的作用是记录图标包中包含的图标文件名,以及图标文件相对应的应用名。以 values\icon_pack.xml 文件为例,其中第一部分为图标的文件名:

<!-- File name (no suffix) list of all icons in /res/drawable-nodpi/ -->
<!-- Names like "Calendar", "500px", "camera_360" are not allowed or recommended. -->
<string-array name="icons" translatable="false">
    <!-- A -->
    <item>alipay</item>
    <item>amazon_kindle</item>
    <item>autonavi</item>  

第二部分为每个图标文件相对应的英文应用名:

<!-- Corresponding app name list of all icons in /res/drawable-nodpi/ -->
<string-array name="icon_labels">
    <!-- A -->
    <item>Alipay</item>
    <item>Amazon Kindle</item>
    <item>Autonavi Maps</item>

请谨记,每个图标文件名与应用名之间都必须呈一一对应关系。也就是说,不能出现写了文件名,但应用名有些写了,有些不写的情况。虽然你可以选择全部不写应用名,但我不推荐这么做。

编辑完毕后,就可以打开带着国旗的 zh\icon_pack.xml,这一块用于填写中文应用名:

<!-- Corresponding app name list of all icons in /res/drawable-nodpi/ -->
<string-array name="icon_labels">
    <!-- A -->
    <item>支付宝</item>
    <item>亚马逊 Kindle</item>
    <item>高德地图</item>

自此,icon_pack.xml 修改完成。接下来需要修改的是 drawable.xml,位于 /res/xml 目录下:

这个文件的作用又是什么呢?你可以在 Nova Launcher 中直接浏览图标包,而且会发现它还能分门别类地显示图标:

而这个特性的背后就是 drawable.xml 的功劳了:它用于给 Nova Launcher 等启动器提供图标选择列表,同时告诉启动器哪些图标属于哪个类型。

NanoIconPack 模版默认提供了三个不同的分类。如果你嫌麻烦,就基于这三个分类编辑就好。第一个分类「Basic」中存在一些占位符:

<category title="Basic" /><!-- Copy basic icons here from All category -->
<!--<item drawable="browser" />-->
<!--<item drawable="calculator" />-->
<item drawable="calendar" />
<!--<item drawable="camera" />-->
<!--<item drawable="clock" />-->

你或许已经注意到了,item drawable= 后跟着的是每个图标的文件名。所以,务必注意不要写错。

如果你听了我上文中的劝告(命名常用系统应用的图标文件名),你现在需要做的就是,把占位符开头的 <!-- 和结尾的 --> 删除。就像这样:

<category title="Basic" /><!-- Copy basic icons here from All category -->
<item drawable="browser" />
<item drawable="calculator" />
<item drawable="calendar" />
<item drawable="camera" />
<item drawable="clock" />

然后,剩下的两个分类「Game」和「Alternative」,你可填写可不填写,如果不想填写的话,删掉就好。但是结尾的「All」分类一定要填,像这样将图标包的所有文件都填进去:

填写完毕后,这个文件的工作也结束了。最后,我们要找到与 drawable.xml 同样位于 /res/xml 目录下的 appfilter.xml

可别小看它,这个文件非常重要!它决定了每个图标与程序之间的对应关系,也就是说,因为有它的存在,启动器才可以自动识别图标包中适配的应用,并将图标覆盖到每个应用上。

这个文件由许多条 <item /> 代码所组成,一条代码的结构大致如此:

<item 
component="ComponentInfo{[包名]/[启动 Acrivity 名]}" 
drawable="[图标文件名]" />

应用包名是每个 Android 应用的唯一标识符,系统依据包名来判断并识别应用。纵使一个应用改名换姓,只要包名一致,系统就会认为它们是同一个应用。

举个例子:有一天,我派的 Cuto 壁纸突然决定将应用名改成 Otuc,图标也改掉了。

但在安装 Otuc 时,由于我派在改名字的时候没有改掉包名,系统依然判断「Otuc」和「Cuto」是同一个应用,会直接将旧应用做更新处理,而不是重新装一个新的。

另一个「启动 Activity」是一个比较复杂的概念,简单来说就是,它决定了当你在启动器上点击图标时,应用会打开哪个页面。

所以,这两个元素是图标包区分应用的关键;而这也允许了不同应用使用同一个图标文件。

举个例子,在一台 Google Pixel 上,「相机」应用的 <item />适配代码大致是这样的:

<item
    component="ComponentInfo{com.google.android.GoogleCamera/com.android.camera.CameraLauncher}"
    drawable="camera" />

而对于一加手机而言,适配代码则会变成:

<item
    component="ComponentInfo{com.oneplus.camera/com.oneplus.camera.OPCameraActivity}"
    drawable="camera" />

看出来了吗?由于手机厂商的不同,「相机」应用的包名和启动 Activity 均有区别;但以这种方式,它们都可以调用图标包中的 camera.png 文件。

那么,问题又来了:该去哪里找这些包名和启动 Activity 呢?毕竟对于这些基本应用来说,每家手机厂商可能都不一样,工作量还是颇大的。

好在开发者 By_syk 为我们提供了一个值得参考的模版文件,其中已经包含了很多系统应用以及常见应用的 <item /> 代码,只要寻找自己图标包中包含的应用,然后复制粘贴就可以了。

但如果你想要适配的应用,模版中也不存在,怎么办?这时候就需要用到 Package Name Viewer 2.0 这款小工具了。

小工具会将手机中已安装的应用分为用户应用和系统应用两类,你可以选择手动翻找,或是进行搜索。再用 Cuto 做个例子,在列表中找到 Cuto 之后,点击就能看到这个窗口:

上方的 com.sspai.cuto.android 即为包名,下方的 com.sspai.cuto.android.EntryActivity 自然就是启动 Activity 了。你可以选择复制并发送到电脑上,按上方的说明填写 <item />代码。

至此,添加图标的部分就结束了。这一块的具体工作量取决于你想要适配的图标多少,但也是最麻烦的一部分,需要有一定的耐心去编辑文件。

好在,结束了这一块之后图标包已经趋近完成了,接下来的工作都很简单。

配置图标包

正如上文所述,Android 系统需要依照应用包名来识别应用,所以你也要为你的图标包起一个包名,顺便还要为它设置一个版本号。

找到左侧的 Gradle Scripts 选项,双击打开 build.gradle (Module: app) :

再找到文件中的 defaultConfig 区域。其中 applicationId 即为包名:

包名的起名方式可以参考如下模版:com.[你的名字].iconpack.[图标包的名字] (均只能使用英文字母)

versionCode 和 versionName 均为版本号的一部分,前者可以理解为「内部版本号」,后者则是显示在前台的版本号,可以依据你自己的想法进行设置。

另外在这一部分还需要注意,如果你希望你的图标包能向下兼容(最低 Android 5.0),那么你需要填入 minSdkVersion 和 targetSdkVersion

后者填入最新的 SDK 版本即可(Android 8.1, API Level 27),而前者决定了应用最低可以在哪个版本的系统上安装,建议填入代表 Android 5.0 的 21.

既然图标包也是一个应用,那么你显然需要为它准备一个图标 —— 严格来说是四个。

说是四个图标,原因是应用图标文件 ic_launcher.png 分布在 /mipmap-hdpi/mipmap-xhdpi/mipmap-xxhdpi/mipmap-xxxhdpi 这四个目录下,它们分别代表着四个不同的分辨率:72*7296*96144*144 和 192*192

不过这倒不是什么麻烦事,做一个最大分辨率的图标,再分别缩放保存即可。

接下来,回到 Android Studio 的项目中,我们需要编辑一下 /res/values 下的 strings.xml

这个文件是用来决定图标包的名字、作者,以及显示在图标包「关于」界面中的内容的。

app_name 处用于填写图标包的名字,developer_name 处填写你自己的名字。

文件下面的内容会在「关于」界面中显示。 NanoIconPack 默认自带了很多内容占位符,包括图标包作者、捐赠信息等。如果你不需要显示某项信息,可以自行留空,但不要删除。

这个文件和 icon_pack.xml 一样,也有一个 带国旗的 zh\ 版本(如上图所示),记得一并编写。最后呈现在应用中的效果就像这样:

信息允许换行,但需要使用 \n 作为换行符。另外,一些特定符号(比如说版权所有的©️)需要使用代码代替,请注意 Android Studio 提示的错误信息。

NanoIconPack 还可以编辑图标包应用的主题色,相关文件是位于 /res/values 下的 colors.xml

如果你不太熟悉颜色的代码以及搭配,可以试试在 Material Palette 网站上随便选两个看上去顺眼的颜色,它会自动帮你生成一套搭配方案。

具体的效果如下:

到了这一步,图标包的开发工作已经接近尾声,接下来要做的,就只剩测试和打包了!

测试并打包

万事俱备,只欠打包;你很快就能用上自己 DIY 的图标包了!

不过在打包之前,最好还是在设备上测试一下,看看有没有出现什么问题。首先要确认在 Android 设备上启用了开发者选项,并且启用 USB 调试功能。

然后点击 Android Studio 上的 Run 按钮,会弹出窗口,让你选择连接到电脑上的设备:

接下来,点击 OK 即可。如果一切顺利,你就会发现设备上自动打开了图标包应用,确认无误后,就可以打包为 APK 安装包了。

在 Android Studios 中找到 Build → Generate Signed APK

该选项用于生成已经签名好的 APK 安装包,至于如何进行操作,建议参考 Google 官方的文档

只有最后一步需要注意,务必在 Versions 处打上 V1 的勾,不然可能会出现无法安装的情况:

当然,生成安装包时也有可能会出错,具体的错误信息会显示在底部的 Messages 处,请善用搜索引擎,网络上一定会有解决方案。

好了,你的 DIY 图标包已经正式打包完成了!快去启动器上换上试试吧!


> 关注 少数派公众号,读有趣的内容 🎉