- 移动开发
- UI组件
【免费下载链接】Android-Iconics
Android-Iconics - Use any icon font, or vector (.svg) as drawable in your application.
本文以 Android-Iconics 官方升级说明(仓库 MIGRATION.md)为脉络,系统梳理该图标库从 v2.x 到 v5.x 的历次破坏性变更:包括IconicsDrawable属性化改造、Kotlin-first 重构、模块拆分与 AndroidX 迁移,并结合当前仓库源码逐一验证每项变更的落地细节。读者读完可掌握各版本间的适配步骤、新旧 API 对照关系,以及如何基于ITypeface/GenericFont正确注册自定义字体。
升级路线总览
Android-Iconics 的演进并非线性小步迭代,而是包含多次破坏性重构。从官方升级说明可以提炼出四条关键的迁移主线:
| 版本区间 | 核心变化 | 影响面 |
|---|---|---|
| v1.x → v2.0.0 | 引入不带内置字体的 core 包 | 依赖与初始化方式 |
| v2.x → v2.5.0 | 推荐IconicsLayoutInflater取代 baseContext 包装 | 布局注入机制 |
| v2.9.0 | 拆分为 iconics-core 与 iconics-views | 依赖坐标 |
| v3.x → v4.x | Kotlin-first、属性语法、IconicsSize/IconicsColor | 全部代码调用 |
| v4.x → v5.x | with*方法全面属性化、弱化 Context 依赖 | 全部代码调用 |
其中 v3 → v4 与 v4 → v5 是影响最大的两次迁移,下文将结合当前仓库源码逐项展开。
core v4.x.x → 5.x.x:IconicsDrawable属性化与 Context 解耦
v5 对IconicsDrawable做了三件事:把链式with*方法改为属性赋值、将"原始 setter"与"扩展函数"分层、并让 Drawable 依赖Resources/Theme而不是Context。
with* 方法 → 属性
v4 时代的链式调用形如withIcon(...).withColor(...).withSize(...),v5 起一律改为 Kotlin 属性赋值。在 IconicsDrawable.kt 中可以看到,颜色、样式、圆角、边距、轮廓、阴影、偏移、透明度、自动镜像等全部以var属性暴露,且 setter 内部会触发invalidateThis()实现即时重绘。典型对照如下:
// v4 风格(已废弃) IconicsDrawable(context) .withIcon(FontAwesome.Icon.faw_android) .withColor(Color.RED) .withSizeDp(24) // v5 风格(属性赋值) IconicsDrawable(context).apply { icon = FontAwesome.Icon.faw_android colorInt = Color.RED sizeDp = 24 }注意icon =、colorInt =、sizeDp =这类属性并不都直接定义在类体内:IconicsDrawable只保留最底层的原始属性(sizeXPx、colorList、paddingPx等),而colorInt、sizeDp、paddingDp这类带单位或资源解析语义的属性被移到了扩展函数中,见 IconicsDrawableExtensions.kt。这样做的目的是把IconicsDrawable类体压缩为纯绘制核心,单位换算、资源提取等逻辑全部下沉到utils扩展层,正如官方升级说明所述:"Raw setters are now direct (int color, string, pixel values), all other properties were moved into extension functions to clean up theIconicsDrawable"。
依赖 Resources 与 Theme,弱化 Context
v5 的IconicsDrawable构造函数签名改为IconicsDrawable(res: Resources, theme: Theme? = null)(见 IconicsDrawable.kt),同时保留IconicsDrawable(context: Context)便捷构造(内部取context.resources与context.theme并调用Iconics.init)。所有"按资源取值"的操作,如IconicsSizeRes.extract(res)与IconicsColorRes.extractList(res, theme),均显式传入Resources与Theme:
- IconicsSize.kt:
dp()、px()、res()三种尺寸描述方式; - IconicsColor.kt:
colorInt()、colorRes()、colorList()、parse()四种颜色描述方式; - 例如
IconicsColorRes.extract()在 API 23+ 使用res.getColor(colorRes, theme)以便正确解析主题属性。
这意味着迁移时要将原本只传context的构造与赋值调用,改为同时依赖res/theme,或在组件中直接传递resources与theme。
XML 使用与 apply 语义
- XML 支持:v5 起
IconicsDrawable可通过 XML 直接引用(API 24+ 支持 inflate 时读取自定义样式属性)。类中重写的inflate()通过 IconicsAttrsExtractor 从R.styleable.Iconics中解析ico_icon、ico_color、ico_size、ico_padding、ico_shadow_*、ico_automirror等全部属性,对应定义见 iconics-core/src/main/res/values/attrs.xml。 apply语义优化:IconicsDrawable.apply { }会先关闭invalidationEnabled,待 block 内所有属性改完后再统一invalidateSelf()(见 IconicsDrawable.kt)。因此批量设置属性时请使用apply {}包裹,避免每次赋值都触发一次重绘。
core v3.x.x → 4.x.x:Kotlin-first 重构
v4 起库全面转向 Kotlin,带来了一系列结构性变化,官方升级说明逐条列出,这里结合源码逐一验证。
字体存储:从 assets 到 font 资源
v3 及更早版本将字体放在assets目录下(GenericFont旧方案通过Typeface.createFromAsset加载);v4 起字体统一迁移到各 typeface 库的res/font资源目录。以社区 Material 图标为例,字体文件位于 community-material-typeface-library/src/main/res/font/community_material_design_icons_font_v7_0_96.ttf,并通过R.font.xxx暴露。
Iconics:不再需要手动传 Context
v3 时代需要手动调用Iconics.init(context)并持有 context。v4 起初始化改由ContentProvider自动完成:新增的 IconicsInitializer.kt 基于 androidx.startup 在应用启动时把applicationContext写入 IconicsHolder.kt。各 typeface 库(如 community-material-typeface-library 的 Initializer.kt)再通过dependencies()声明对IconicsInitializer的依赖,并在create()中调用IconicsHolder.registerFont(...)完成字体注册。
IconicsBuilder → Builder
Iconics.IconicsBuilder更名为Iconics.Builder,并移除了ctx(Context)方法。当前 Iconics.kt 中Builder仅保留style(...)、styleFor(...)、font(...)与on(...)四个方法,配合BuilderString.build()/BuilderView.build()将占位文本替换为图标字形。
IconicsDrawable:IconicsSize / IconicsColor 与属性语法
- 所有
*Res(int)、*Px(int)、*Dp(int)方法被替换为IconicsSize与IconicsColor类型; - 常量
TOOLBAR_ICON_SIZE(24dp)与TOOLBAR_ICON_PADDING(1dp)移入 IconicsSize.kt,可直接通过IconicsSize.TOOLBAR_ICON_SIZE引用; - 所有 getter 改为属性语法(见上文 v5 部分);
- 原 Android-Iconics-Kt 扩展提供的"生产者式"方法被并入类中,返回可空值、仅当非空时才赋值——对应实现见 IconicsDrawableProducerExtensions.kt(如
icon(iconProducer: () -> String?)、size(sizeProducer: () -> IconicsSize?)); enableShadowSupport(View)移至IconicsUtils,实现为view.setLayerType(View.LAYER_TYPE_SOFTWARE, null),见 IconicsUtils.kt,并提供了扩展函数View.enableShadowSupport()(IconicsExtensions.kt)。
ITypeface 接口改造
ITypeface的核心变化是getTypeface(Context)方法被替换为rawTypeface字段。当前接口定义见 ITypeface.kt:
interface ITypeface { val rawTypeface: Typeface get() = runCatching { ResourcesCompat.getFont(IconicsHolder.applicationContext, fontRes) }.getOrNull() ?: Typeface.DEFAULT @get:FontRes val fontRes: Int val characters: Map<String, Char> val mappingPrefix: String // 必须是 3 位前缀 val fontName: String val version: String val iconCount: Int val icons: List<String> val author: String val url: String val description: String val license: String val licenseUrl: String fun getIcon(key: String): IIcon }rawTypeface由fontRes自动从字体资源加载——官方说明中提到的旧方案GenericFont仍保留在 GenericFont.kt(基于assets的Typeface.createFromAsset加载方式),如果你还在使用 assets 方案可参考它适配。同时,所有utils类与 typeface 库实现为不可实例化的单例(object)。
Community Material Icons > v2.7.94:枚举拆分
当 Community Material 图标数量超出单枚举上限后,图标被拆分为CommunityMaterial.Icon、CommunityMaterial.Icon2(当前仓库实际为Icon/Icon2/Icon3三份枚举,见 CommunityMaterial.kt)。拆分规则:以字母h为界,a~g在Icon,h~z在Icon2。使用代码时需按图标字母选择对应枚举;getIcon(key)内部会依次尝试各枚举(见 CommunityMaterial.kt),因此通过字符串名称查找不受拆分影响。
v3.1.x:AndroidX 迁移
v3.1.x 起库使用 AndroidX 依赖,项目必须同步迁移到 AndroidX。从当前仓库的源码可以印证:核心类大量使用androidx.core.content.res.ResourcesCompat、androidx.core.graphics.drawable.DrawableCompat、androidx.startup.Initializer、androidx.appcompat.app.AppCompatDelegate等 AndroidX API(例如 ITypeface.kt 与 IconicsExtensions.kt)。仍在用appcompat且未迁移 AndroidX 的项目,应使用 v3.1.x 之前的版本。AndroidX 迁移的详细步骤可参考官方迁移指南(https://developer.android.com/topic/libraries/support-library/refactor)。
2.9.x:模块拆分与属性前缀调整
2.9.5:菜单属性iiv_→ico_
IconicsMenuInflaterUtil相关的 XML 属性前缀由iiv_改为ico_,同时该工具类从 views 模块移入 core 模块。当前实现位于 IconicsMenuInflaterUtil.kt:inflate(inflater, context, menuId, menu, checkSubMenus)先执行标准 inflate,再通过parseXmlAndSetIconicsDrawables解析菜单 XML 中的ico_*样式属性并设置menuItem.icon。配套的MenuInflater.inflateWithIconics(...)与Menu.parseXmlAndSetIconicsDrawables(...)扩展见 IconicsExtensions.kt。
2.9.0:iconics-core / iconics-views 拆分
library-core 被拆分为iconics-core与iconics-views:core 保持轻量(Drawable、Builder、工具类),所有 UI 控件(IconicsImageView、IconicsTextView、IconicsButton、IconicsCheckBox、IconicsCheckableTextView、IconicsImageButton、IconicsCompoundButton)下沉到 views 模块(见 iconics-views)。当前仓库的模块声明见 settings.gradle。依赖配置:
// 基础依赖 compile "com.mikepenz:iconics-core:2.9.0@aar" // 需要 UI 控件时追加 compile "com.mikepenz:iconics-views:2.9.0@aar"2.8.0:最低 API 提升到 14
v2.8.0 起放弃对 API < 14 的支持,MinSdkVersion提升为 14。若你的项目minSdk < 14,需要先提升后再升级该版本。
2.x → 2.5.0:从 Context 包装到 LayoutInflater 工厂
这是布局注入机制的一次重要转向,官方给出了两种方案,推荐前者:
方案一:设置 IconicsLayoutInflater 为默认 LayoutInflater
在Activity的onCreate中(需要继承AppCompatActivity或实现AppCompatDelegate),将IconicsLayoutInflater设为默认工厂:
@Override protected void onCreate(Bundle savedInstanceState) { LayoutInflaterCompat.setFactory(getLayoutInflater(), new IconicsLayoutInflater(getDelegate())); //... super.onCreate(savedInstanceState); //... }该方案相比包装baseContext的优势是能与 Calligraphy 等同样包装baseContext的库兼容。当前仓库中 IconicsLayoutInflater.kt 与 IconicsLayoutInflater2.kt 即为该机制的实现:它们委托AppCompatDelegate.createView(...)创建视图,再经IconicsFactory.onViewCreated处理ico_*属性。在 Kotlin 中可直接使用扩展函数layoutInflater.setIconicsFactory(appCompatDelegate)(IconicsExtensions.kt),它会按 API 级别自动选择IconicsLayoutInflater2(API 26+)或IconicsLayoutInflater。
注意:当前仓库已在IconicsLayoutInflater与IconicsContextWrapper上标注@Deprecated(提示改用IconicsImageView/IconicsTextView等专用控件),说明该机制在新版本中已被专用 View 取代,但仍可用于理解历史迁移路径。
方案二:包装 baseContext(备选)
如果未使用其他包装BaseContext的库、未继承AppCompatActivity或未实现AppCompatDelegate,仍可包装baseContext:
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(IconicsContextWrapper.wrap(newBase)); }IconicsContextWrapper.kt 通过覆写getSystemService(),在请求LAYOUT_INFLATER_SERVICE时返回内部InternalLayoutInflater。
v1.x → v2.0.0:core 包不再内置字体
v2.0.0 引入的 core 包默认不包含任何字体,需要按需引入 typeface 库(本仓库在 settings.gradle 中收录了社区 Material、DevIcon、Entypo、FontAwesome、Foundation Icons、Google Material(filled/outlined/rounded/sharp)、Material Symbols、Ionicons、MaterialDesignDx、MaterialDesignIconic、Meteocons、Octicons、Phosphor、Pixeden 7 Stroke、Simple Icons、Typeicons、Weather Icons 等十余个字体库)。自定义字体则通过实现ITypeface完成——可直接参考示例 CustomFont.kt:定义object CustomFont : ITypeface,声明fontRes指向R.font.fontello、mappingPrefix = "fon",并通过枚举Icon列出fon_test1、fon_test2等字符映射。
字体包(Font Addons)变更备忘
Google Material font v2.1.0.1.original
- 该字体重新成为默认 Google Material 图标集,映射前缀为"gmd",包名为
com.mikepenz.google_material_typeface_library.GoogleMaterial(当前仓库位于 google-material-typeface-library); - 注意事项:Google 字体的基线不佳,图标在文本中无法居中,但作为 Drawable 显示正常;若此问题影响使用,可改用 Material Design Iconic 作为替代。
Material Design Iconic v2.2.0.1
- 成为独立的 Material Design Iconic 图标包,映射前缀为"gmi",包名为
com.mikepenz.material_design_iconic_typeface_library.MaterialDesignIconic(当前仓库位于 MaterialDesignIconic.kt)。示例代码IconicsDrawable(this, MaterialDesignIconic.Icon.gmi_search)可参见 MainActivity.kt。
Google Material font 1.2.0.1 → 2.1.2.1
- 部分图标的字符映射发生变化,升级后请核对已使用图标是否仍渲染正确。
迁移后的验证与调试建议
- 确认初始化:
IconicsHolder.applicationContext未初始化时访问会抛出RuntimeException("A 'Iconics.init(context)' has to happen first...")(见 IconicsHolder.kt)。v4+ 由 androidx.startup 自动完成,若自研 ContentProvider 或启动器被裁剪,需显式调用Iconics.init(context)。 - 检查字体注册:
Iconics.init会提示 "At least one font needs to be registered first",注册入口为Iconics.registerFont(font)(Iconics.kt)。 - 验证图标字符串:
Iconics.isIconExists(icon)可检测"gmd_xxx"形式的三位前缀 + 图标名是否有效;iconPrefix与clearedIconName两个扩展(IconicsExtensions.kt)负责解析前缀(取前 3 字符)并把-替换为_。 - 对比新旧 API:升级报错集中在
with*方法与*Res/*Px/*Dp后缀方法上,按上文表格中的对照关系机械替换即可;sizePx、size、roundedCornersPx、roundedCorners等旧 getter 已在 IconicsDrawableExtensions.kt 中被标记为DeprecationLevel.ERROR,编译器会直接拦截,引导你改用sizeXPx/sizeYPx/roundedCornerRxPx/roundedCornerRyPx等新属性。
小结
Android-Iconics 的升级路径本质上是"从 Java 链式风格走向 Kotlin 属性化、从 Context 绑定走向 Resources/Theme 解耦、从 assets 字体走向 font 资源"的过程。把握住IconicsDrawable属性化、ITypeface.rawTypeface、IconicsSize/IconicsColor类型、androidx.startup 自动初始化这四条主线,即可按版本号逐级完成迁移。当前仓库(含各 typeface 库、示例 app 与 MIGRATION.md 原文)是核对新旧 API 行为的最佳参考,建议迁移时以仓库源码为最终依据。
- 移动开发
- UI组件
【免费下载链接】Android-Iconics
Android-Iconics - Use any icon font, or vector (.svg) as drawable in your application.
相关推荐
GraphQL.NET v5 迁移完全指南:从 v4.x 升级到 v5.x 的新特性与破坏性变更
GraphQL.NET v5 迁移完全指南:从 v4.x 升级到 v5.x 的新特性与破坏性变更 导读 本文基于 docs2/site/docs/migrati
后端Nuke 14 迁移指南:从 Nuke 13.x 升级的完整 API 变更与适配方案
Nuke 14 迁移指南:从 Nuke 13.x 升级的完整 API 变更与适配方案 本指南面向正在使用 Nuke 13.x 并准备升级到 Nuke 14 的开
移动开发图像处理Monolog 2.x/3.x/4.x 升级迁移完全指南:API 变更、代码迁移与实战改造
Monolog 2.x/3.x/4.x 升级迁移完全指南:API 变更、代码迁移与实战改造 导读 本文基于 Monolog 仓库中的 UPGRADE.md ht
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考