Android:更好的自定义字体方案
http://ryanhoo.github.io/blog/2014/05/05/android-better-way-to-apply-custom-font/
原文:http://vision-apps.blogspot.hk/2012/02/android-better-way-to-apply-custom-font.html
在一个应用中,我需要在所有的UI组件中使用客户提供的字体。这听起来似乎是个很稀松平常的任务,不是吗?是的,我当时也是这么想的。然后我震惊了,Android竟然没有提供一个简单优雅的方式来做这件事情!
所以,在这篇文章中我会展示Android提供的默认方法,然后我会分享更加简单优雅的解决方案。
情景
你需要为整个应用替换自定义字体。
解决方案
1)Android默认方法 #1
你可以通过ID查找到View,然后挨个为它们设置字体。在单个View的情况下,它看起来也没有那么可怕。
1 |
|
但是在很多TextView、Button等文本组件的情况下,我敢肯定你不会喜欢这个方法的。:D
2)Android默认方法 #2
你可以为每个文本组件创建一个子类,如TextView、Button等,然后在构造函数中加载自定义字体。
1 |
|
然后只需要将标准的文本控件替换成你自定义的就可以了(例如BrandTextView替换TextView)。
1 |
|
还有,你甚至可以直接在XML中添加自定义的字体属性。要实现这个,你需要定义你自己的declare-styleable属性,然后在组件的构造函数中解析它们。
为了不占篇幅介绍这么基础的东西,这里有一篇不错的文章告诉你怎么自定义控件属性。
http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
在大多数情况下,这个方法还不赖,并且有一些优点(例如,切换字体粗细等等,字体可以在组件xml文件的typeface属性中定义)。但是我认为这个实现方法还是太重量级了,并且依赖大量的模板代码,为了一个替换字体的简单任务,有点儿得不偿失。
3)我的解决方案
理想的解决方案是自定义主题,然后应用到全局或者某个Activity。 但不幸的是,Android的android:typeface属性只能用来设置系统内嵌的字体,而非用户自定义字体(例如assets文件中的字体)。这就是为什么我们无法避免在Java代码中加载并设置字体。
所以我决定创建一个帮助类,使得这个操作尽可能的简单。使用方法:
1 |
|
并且这行代码会用来加载所有的基于TextView的文本组件(TextView、Button、RadioButton、ToggleButton等等),而无需考虑界面的布局层级如何。

这是怎么做到的?非常简单:
1 |
|
正如你所看到的,所需要做的仅仅是将基于TextView的文本组件从布局中遍历出来而已。
你可以在这里下载到示例代码,里面有FontHelper的具体用法。
译者注
在多个项目中,我都碰到过类似的需求,早期采用的是第二种实现方法,但是缺点在于对于第三方组件,你需要去修改别人的代码,才能实现自定义字体,这恰恰违反了OC(Open & Close)原则,对扩展开放,对修改封闭。
刚看到第三种的时候,也是惊为天人,姑且不说结果,我觉得这种活跃的思路非常重要,很值得学习参考。
但是最后被team里的人否决了,理由是违背组件设计原则,实现方式略嫌粗暴。后来我仔细想想,一个是要做好内存管理(似乎会引起内存问题),视图状态改变,也要重复加载(横竖屏、onResume等),也绝对不是简单的活儿。
所以暂定使用第一种方法,typeface使用单例,需要时设置字体。
我个人觉得第一种还是个体力活,而且到后来,这个代码重复率还是非常高的,这又违背了DRY原则。
在地铁上的时候,突然想到DI(Dependency Inject)。已经有一些DI的框架,如ButterKnife,那写出来应该是这样:
1 |
|
or
1 |
|
这样写出来代码相比重复写setTypeface要好一些。
目前我们的项目还没有使用这类DI框架,等以后引入了,使用第二种注入,写起来应该是很爽的。
保持更新。
参考
Android:更好的自定义字体方案的更多相关文章
- Android中快速实现自定义字体!
前言:我们都知道,Android中默认的字体是黑体,而大多数app也都是使用的这种字体,但我们发现,大多数app中,个别地方字体非常好看,例如app的标题栏,菜单栏等地方,那他们是怎么做到的呢?有两种 ...
- Android控件使用自定义字体
我们不可能只满足于系统自带的字体(太丑),其实控件自定义字体也很简单.. 1.首先找到该字体的ttf文件. 2.把字体文件放在scr/mian/assets/fonts下,如果没有该路径则自己创建. ...
- 【Android 界面效果42】如何自定义字体
项目里要统一用设计师的字体,android:typeface只支持系统三种字体.有什么比较好的做法? 你需要为整个应用替换自定义字体. 解决方案 1)Android默认方法 #1 你可以通过ID查找到 ...
- Android 中使用自定义字体的方法
1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . <?xml version="1.0 ...
- 转--Android中自定义字体的实现方法
1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . 复制代码 代码如下: <?xml versio ...
- Android实现自定义字体
介绍 最近在看开源项目的时候,发现里面涉及到了自定义字体,虽然自己目前还用不到,但是动手demo笔记记录一下还是有必要的,没准哪天需要到这个功能. 原理 1.其实实现起来非常简单,主要是用到了Type ...
- Android 使用自定义字体
整个项目要使用第三方字体首先将字体文件放到assets文件夹下 因为整个项目要用第三方字体这里我重写了 TextView Button EditText 三个控件 以TextView 为例代码如下 ...
- Android Studio设置自定义字体
Android Studio设置自定义字体 (1)进入设置页面,File->Settings (2)自定义字体Editor->Colors&Fonts->Font (3)点击 ...
- Android 开发使用自定义字体
有时候,系统自带的字体并不能满足我们特殊的需求,这时候就需要引用其他的字体了,可以把下载的字体文件放在 assets 目录下. 自定义字体文件不能使用xml代码读取而应该使用java代码: publi ...
随机推荐
- eclipse取消自动输入提示
在设置Eclipse自动提示后,按a-z都会显示提示,但是我们需要键入Enter才会输入,而默认的所有都键入,非常弱智,可采用下面方法设置. 1,先找到相关的插件: window -> show ...
- 案例学python——案例一:抓图
最近项目不那么紧张,有时间来研究一下Python,先前断断续续的自学了一段时间,有些浅基础.刚好在码云上看到比较适合的案例,跟着案例再往前走一波. 案例一:爬虫抓图 开发工具:PyCharm 脚 ...
- item 8: 比起0和NULL更偏爱nullptr
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 先让我们看一些概念:字面上的0是一个int,不是一个指针.如果C+ ...
- Flask-sqlalchemy 语法总结
Flask-sqlalchemy 语法总结 ** DDLdb.create_all() :创建实体表db.drop_all(): 删除表 1)插入表Db.session.add(user) #user ...
- Http指南(3)
Web主机托管 主机托管服务 虚拟主机托管:许多Web托管者通过让一些顾客共享一台计算机来提供便宜的Web主机托管服务.这称为共享主机托管或虚拟主机托管 虚拟服务器请求缺乏主机信息: 不幸的是,HTT ...
- django通用权限控制框架
在web项目中根据不同的用户肯定会限制其不同的权限,利用以下模块可以满足日常几乎所有的权限控制 permission_hook.py # 自定义权限控制,必须返回True/false ,True表 ...
- 《Linux内核设计与实现》读书笔记 3
第三章 进程管理 3.1进程 概念: 进程:处于执行期的程序.但不仅局限于程序,还包含其他资源(打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内催音社的内存地址空间及一个或多个执行线 ...
- github 学习心得
https://github.com/kongxiangyu/test 通过本次实验,学会了如何使用github来管理代码.如果是开源的项目,通过网站托管方式进行统一管理,当然是非常棒的,并且有很多功 ...
- 基于SSH实现员工管理系统之框架整合篇
本篇文章来源于:https://blog.csdn.net/zhang_ling_yun/article/details/77803178 以下内容来自慕课网的课程:基于SSH实现员工管理系统之框架整 ...
- Node require
var user = require("./module_user");//使用模块 module_userconsole.log(user.userCount);user.use ...