- UI组件
- 移动开发
【免费下载链接】Android-Bootstrap
Bootstrap style widgets for Android, with Glyph Icons
本文基于仓库根目录的 ADD_FONT.md 官方扩展指南,结合 Android-Bootstrap 库的 TypefaceProvider、IconSet 及内置图标集源码,系统讲解如何为 Android-Bootstrap 接入一套全新的图标字体,并覆盖 IconSet 接口实现、TTF 资源放置、TypefaceProvider 注册、BootstrapText 拼接图标与常见踩坑点,帮助读者快速将任意开源图标字体变成项目可用的 Glyph Icon 集。
AwesomeTextView 是承载各 Icon Set 字体图标的容器控件,新接入的图标字体最终都通过它渲染(图片来源:仓库 images 目录)
1. 为什么 Android-Bootstrap 需要“字体图标集”
Android-Bootstrap 通过Typeface Icon Sets(字体图标集)提供可缩放的图形,其核心思路是:把图标字形放进 TTF 字体文件,用 unicode 码位代替图片资源。这样做的好处是无需为不同屏幕密度(mdpi / hdpi / xhdpi / xxhdpi / xxxhdpi)准备多套 drawable,图标随字体大小、颜色缩放而自动适配,这正是 ADD_FONT.md 开篇点明的设计动机。
仓库默认在 AndroidBootstrap/src/main/assets 下内置了三套字体文件:
| 字体文件 | 对应 IconSet 实现 | 字体路径常量 |
|---|---|---|
fontawesome-webfont-v470.ttf | FontAwesome.java | FontAwesome.FONT_PATH |
typicons-v207.ttf | Typicon.java | Typicon.FONT_PATH |
MaterialIcons-Regular.ttf | MaterialIcons.java | MaterialIcons.FONT_PATH |
三者的字体路径常量分别对应"fontawesome-webfont-v470.ttf"、"typicons-v207.ttf"与"MaterialIcons-Regular.ttf",均以 assets 目录为起点。官方鼓励社区提交新字体:按本指南完成接入后,可以向项目发送 Pull Request 请求将新图标集默认集成进库中(见 ADD_FONT.md 第 1 步末尾的说明)。
2. 接入自定义字体:官方六步流程
ADD_FONT.md 给出了一套明确的六步接入流程,以下逐步展开并结合源码补充实现细节。
步骤 1:找到字体的 Reference Sheet 并编写解析脚本
接入的第一步,是找到目标字体官方的reference sheet(图标速查表)——它列出了每个图标对应的字体 unicode 码位。例如 FontAwesome 官方 Cheatsheet、Typicons 官网图标表。拿到表格后,用脚本解析成“图标名 → unicode 字符”的映射数据,供后续填充到 IconSet 实现中。
官方提示:FontAwesome 与 Typicon 两套内置图标集都曾借助解析脚本自动生成(两者类内均有// Auto-generated Icon Set from 2015-10-05的注释标记,见 FontAwesome.java 与 Typicon.java),如果你也编写了解析脚本,欢迎连同脚本一起提交 Pull Request。
步骤 2:实现 IconSet 接口
新建一个类实现 IconSet 接口。该接口用三个方法描述“字体在 assets 中的位置”与“图标码到 unicode 字符的映射”:
public interface IconSet { /** * 根据图标 code(如 "my_icon")返回对应的 unicode 字符 */ CharSequence unicodeForKey(CharSequence key); /** * 根据 XML 属性中的枚举索引返回图标 code(供布局文件属性使用) */ CharSequence iconCodeForAttrIndex(int index); /** * 返回字体文件在 assets 目录下的路径,例如 "myicons.ttf" */ CharSequence fontPath(); }参照内置实现(如 FontAwesome.java),一个自定义图标集大致长这样:
public class MyIcons implements IconSet { public static final String FONT_PATH = "myicons.ttf"; private static final Map<String, String> ICON_MAP = new HashMap<>(); private static final Map<Integer, String> ATTR_MAP = new HashMap<>(); static { // 步骤 1 解析脚本生成的映射数据填充于此,例如: ICON_MAP.put("my_heart", "\ue001"); ICON_MAP.put("my_star", "\ue002"); // ATTR_MAP:为每个图标分配一个 XML 枚举索引 ATTR_MAP.put(0, "my_heart"); ATTR_MAP.put(1, "my_star"); } @Override public CharSequence unicodeForKey(CharSequence key) { return ICON_MAP.get(key); } @Override public CharSequence iconCodeForAttrIndex(int index) { return ATTR_MAP.get(index); } @Override public CharSequence fontPath() { return FONT_PATH; } }命名与映射要点(源码明文约束):
- 库内图标 code 统一使用下划线而非连字符。FontAwesome 的 Javadoc 明确说明:“icon codes use underscores rather than hyphens in this library. For example, 'fa-play' would become 'fa_play'”,原因是 Android 属性(Attribute)命名不允许使用连字符;
unicodeForKey与iconCodeForAttrIndex返回CharSequence而不是String,实现时注意类型一致性。
步骤 3:将字体 TTF 文件拷贝到 assets 目录
把下载好的 TTF 文件放入库/应用的assets/目录,文件名必须与fontPath()返回值严格一致(例如myicons.ttf)。仓库内置三套字体的放置方式可直接参考 AndroidBootstrap/src/main/assets:
assets/ ├── MaterialIcons-Regular.ttf ├── fontawesome-webfont-v470.ttf └── typicons-v207.ttf步骤 4:通过 TypefaceProvider 注册自定义图标集
调用 TypefaceProvider.registerCustomIconSet() 完成注册,使新图标集在整个应用内可用:
TypefaceProvider.registerCustomIconSet(new MyIcons());从源码看,TypefaceProvider 内部维护了两张静态缓存表:
TYPEFACE_MAP:Map<CharSequence, Typeface>,按字体路径缓存Typeface.createFromAsset()创建的字体实例,避免反复初始化开销;REGISTERED_ICON_SETS:Map<CharSequence, IconSet>,按字体路径缓存已注册的 IconSet。
registerCustomIconSet本质就是把(iconSet.fontPath(), iconSet)放入REGISTERED_ICON_SETS。若在运行时视图向retrieveRegisteredIconSet()请求一个未注册字体路径,会直接抛出RuntimeException(提示 “Font 'xxx' not properly registered”),因此注册动作务必在视图创建前完成。
推荐做法与内置示例应用一致——在自定义Application的onCreate()中注册。仓库示例 SampleApplication.java 展示了默认图标集的注册方式:
public class SampleApplication extends Application { @Override public void onCreate() { super.onCreate(); // 注册默认图标集:FontAwesome、Typicon、MaterialIcons TypefaceProvider.registerDefaultIconSets(); // 自定义图标集追加注册 TypefaceProvider.registerCustomIconSet(new MyIcons()); } }注意:
registerDefaultIconSets()与registerCustomIconSet()并不互斥——默认注册的三个图标集同样是以“按字体路径写入注册表”的方式登记的(见 TypefaceProvider.java),自定义图标集追加注册即可共存。
步骤 5:用 BootstrapText 在文本中插入新图标
注册完成后,即可使用 BootstrapText.Builder 在富文本中拼接图标。Builder提供了多种追加方法,其中面向自定义图标集的核心方法是addIcon(CharSequence iconCode, IconSet iconSet):
BootstrapText text = new BootstrapText.Builder(this) .addText("点个赞:") .addIcon("my_heart", new MyIcons()) // 自定义图标 .addFontAwesomeIcon(FA_ANDROID) // 内置 FontAwesome 图标 .build(); awesomeTextView.setBootstrapText(text);从 BootstrapText.java 源码可以看出addIcon的底层逻辑:先把iconSet.unicodeForKey(iconCode)查到的 unicode 字符追加进StringBuilder,再在fontIndicesMap中记录该字符的结束位置与对应 IconSet;build()时遍历该 Map,用 AwesomeTypefaceSpan 为每个图标字符打上对应字体的 Span——最终渲染时AwesomeTypefaceSpan.updateDrawState()通过TypefaceProvider.getTypeface()取出字体并应用到 TextPaint。
BootstrapText继承自SpannableString并实现了Serializable,因此可以直接作为控件文本,也能随 Activity 状态一起序列化保存恢复(见 AwesomeTextView.java 的onSaveInstanceState/onRestoreInstanceState)。
步骤 6:测试、提交 Pull Request 或报告 Issue
完成上述步骤后在模拟器/真机上验证新图标集的显示效果:图标是否渲染、大小是否随字号缩放、颜色是否跟随 BootstrapBrand 变化。若一切正常,可按官方建议发送 Pull Request 请求将图标集加入库的默认集合;若发现问题,则按 README.md 的指引提交 Issue。
3. 除了 Builder,还能怎么用图标:XML 属性与 Markdown
接入自定义图标集后,有三条使用途径(对应 attrs.xml 中AwesomeTextView的声明):
方式一:XML 属性(需额外声明 attr 枚举)
内置三套图标分别通过fontAwesomeIcon、typicon、materialIcon三个属性在布局中使用,其枚举值定义在 attrs_font_awesome.xml、attrs_typicons.xml、attrs_materialIcon.xml。渲染时 AwesomeTextView 通过iconCodeForAttrIndex(ordinal)反查图标 code。
<com.beardedhen.androidbootstrap.AwesomeTextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:bootstrapBrand="success" app:fontAwesomeIcon="fa_android" />若希望自定义图标集也支持 XML 属性,需要参照上述 attrs 文件为自己的图标集补充<attr name="myIcon" format="enum">枚举声明,并在AwesomeTextView的declare-styleable中挂接该属性。
方式二:BootstrapText.Builder(推荐,已在上节演示)
通过addIcon(iconCode, iconSet)可在任意位置混合普通文本、不同图标集的图标,灵活度最高。
方式三:Markdown 字符串
AwesomeTextView支持setMarkdownText()/app:bootstrapText属性,用{图标code}语法内联图标。解析逻辑位于 IconResolver.java:
- FontAwesome:
{fa_android}(正则(fa_|fa-)[a-z_0-9]+) - Typicon:
{ty_weather_cloudy}(正则(ty_|ty-)[a-z_0-9]+) - MaterialIcons:
{md_share}(正则(md_)[a-z_0-9]+) - 自定义图标集:
IconResolver.resolveIconSet()会遍历所有已注册的 IconSet(跳过内置三套),调用unicodeForKey()逐一匹配;匹配不到则抛出IllegalArgumentException(见 IconResolver.java)。因此自定义图标集的 markdown 写法就是{my_heart},前提是已注册。
<com.beardedhen.androidbootstrap.AwesomeTextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:bootstrapText="I {fa_heart} {my_star} this library" />另外,IconResolver支持用反斜杠转义花括号(例如\{fa_facebook\}渲染为纯文本),编辑器预览(isInEditMode())时会以?占位代替图标。
4. 常见问题与注意事项
- 忘记注册导致运行时崩溃:任何视图(包括
AwesomeTextView、BootstrapDropDown等使用bootstrapText属性的控件)在解析图标前都会调用retrieveRegisteredIconSet(),未注册的字体路径会抛出RuntimeException。务必在 Application 的onCreate()中完成注册。 - 图标 code 一律使用下划线:连字符会在
Builder.addIcon中被replaceAll("\\-", "_")统一替换,但建议直接按下划线规范编写,保持与内置图标集一致。 - TTF 文件名必须与
fontPath()完全一致:TypefaceProvider.getTypeface()直接以fontPath()作为Typeface.createFromAsset(context.getAssets(), path)的参数,大小写与扩展名都需匹配 assets 中的实际文件。 - 在自定义图标集上使用 XML 属性:需要自行补充 enum 类型的 attr 声明,
iconCodeForAttrIndex()必须为每个枚举索引返回有效图标 code,否则渲染为空白。 - 不要覆盖默认图标集:
REGISTERED_ICON_SETS以字体路径为键,若自定义字体路径与内置三者(fontawesome-webfont-v470.ttf、typicons-v207.ttf、MaterialIcons-Regular.ttf)冲突,会覆盖默认注册项,应避免。
5. 相关源码与资源索引
- 扩展指南原文:ADD_FONT.md
- 图标集接口:IconSet.java
- 内置实现:FontAwesome.java、Typicon.java、MaterialIcons.java
- 注册与字体加载:TypefaceProvider.java
- 富文本拼接:BootstrapText.java、AwesomeTypefaceSpan.java
- Markdown 解析:IconResolver.java
- 属性声明:attrs.xml、attrs_font_awesome.xml、attrs_typicons.xml、attrs_materialIcon.xml
- 字体资源:AndroidBootstrap/src/main/assets
- 应用内注册示例:SampleApplication.java、AwesomeTextViewExample.java
至此,从解析速查表、实现IconSet、放置 TTF、注册到最终在BootstrapText/ XML / Markdown 中使用,一套完整的自定义图标字体接入闭环已全部打通。
- UI组件
- 移动开发
【免费下载链接】Android-Bootstrap
Bootstrap style widgets for Android, with Glyph Icons
相关推荐
wot-design-uni 图标组件(wd-icon)完全指南:内置字体图标、图片图标与自定义 iconfont 的接入实践
wot design uni 图标组件(wd icon)完全指南:内置字体图标、图片图标与自定义 iconfont 的接入实践 导读 wd icon 是 wot
前端UI组件移动开发小程序vant-weapp Icon 图标组件实战指南:从基础用法到自定义字体图标与源码原理
vant weapp Icon 图标组件实战指南:从基础用法到自定义字体图标与源码原理 导读 本文基于 vant weapp https://link.gitc
前端小程序UI组件移动开发深入理解 wot-design-uni 的 wd-icon 图标组件:字体图标、自定义图标与图片图标的实现原理
深入理解 wot design uni 的 wd icon 图标组件:字体图标、自定义图标与图片图标的实现原理 wd icon 是 wot design uni
前端UI组件移动开发小程序
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考