http://ryanhoo.github.io/blog/2014/05/05/android-better-way-to-apply-custom-font/

  • 情景
  • 解决方案
    • 1)Android默认方法 #1
    • 2)Android默认方法 #2
    • 3)我的解决方案
  • 译者注
  • 参考

原文: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
2
3
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/YourCustomFont.ttf"); TextView view = (TextView) findViewById(R.id.activity_main_header); view.setTypeface(customFont); 

但是在很多TextView、Button等文本组件的情况下,我敢肯定你不会喜欢这个方法的。:D

2)Android默认方法 #2

你可以为每个文本组件创建一个子类,如TextView、Button等,然后在构造函数中加载自定义字体。

1
2
3
4
5
6 7 8 9 10 11 12 13 14 15 16 17 18 19 
public class BrandTextView extends TextView {   public BrandTextView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  }  public BrandTextView(Context context, AttributeSet attrs) {  super(context, attrs);  }  public BrandTextView(Context context) {  super(context);  }  public void setTypeface(Typeface tf, int style) {  if (style == Typeface.BOLD) {  super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/YourCustomFont_Bold.ttf"));  } else {  super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/YourCustomFont.ttf"));  }  }  } 

然后只需要将标准的文本控件替换成你自定义的就可以了(例如BrandTextView替换TextView)。

1
2
3
4
5
6 7 8 9 
<com.your.package.BrandTextView
         android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="View with custom font"/> <com.your.package.BrandTextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:textStyle="bold"  android:text="View with custom font and bold typeface"/> 

还有,你甚至可以直接在XML中添加自定义的字体属性。要实现这个,你需要定义你自己的declare-styleable属性,然后在组件的构造函数中解析它们。

为了不占篇幅介绍这么基础的东西,这里有一篇不错的文章告诉你怎么自定义控件属性。

http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

在大多数情况下,这个方法还不赖,并且有一些优点(例如,切换字体粗细等等,字体可以在组件xml文件的typeface属性中定义)。但是我认为这个实现方法还是太重量级了,并且依赖大量的模板代码,为了一个替换字体的简单任务,有点儿得不偿失。

3)我的解决方案

理想的解决方案是自定义主题,然后应用到全局或者某个Activity。 但不幸的是,Android的android:typeface属性只能用来设置系统内嵌的字体,而非用户自定义字体(例如assets文件中的字体)。这就是为什么我们无法避免在Java代码中加载并设置字体。

所以我决定创建一个帮助类,使得这个操作尽可能的简单。使用方法:

1
FontHelper.applyFont(context, findViewById(R.id.activity_root), "fonts/YourCustomFont.ttf");

并且这行代码会用来加载所有的基于TextView的文本组件(TextView、Button、RadioButton、ToggleButton等等),而无需考虑界面的布局层级如何。

这是怎么做到的?非常简单:

1
2
3
4
5
6 7 8 9 10 11 12 13 
public static void applyFont(final Context context, final View root, final String fontName) {  try {  if (root instanceof ViewGroup) {  ViewGroup viewGroup = (ViewGroup) root;  for (int i = 0; i < viewGroup.getChildCount(); i++)  applyFont(context, viewGroup.getChildAt(i), fontName);  } else if (root instanceof TextView)  ((TextView) root).setTypeface(Typeface.createFromAsset(context.getAssets(), fontName));  } catch (Exception e) {  Log.e(TAG, String.format("Error occured when trying to apply %s font for %s view", fontName, root));  e.printStackTrace();  } } 

正如你所看到的,所需要做的仅仅是将基于TextView的文本组件从布局中遍历出来而已。

你可以在这里下载到示例代码,里面有FontHelper的具体用法。

译者注

在多个项目中,我都碰到过类似的需求,早期采用的是第二种实现方法,但是缺点在于对于第三方组件,你需要去修改别人的代码,才能实现自定义字体,这恰恰违反了OC(Open & Close)原则,对扩展开放,对修改封闭。

刚看到第三种的时候,也是惊为天人,姑且不说结果,我觉得这种活跃的思路非常重要,很值得学习参考。

但是最后被team里的人否决了,理由是违背组件设计原则,实现方式略嫌粗暴。后来我仔细想想,一个是要做好内存管理(似乎会引起内存问题),视图状态改变,也要重复加载(横竖屏、onResume等),也绝对不是简单的活儿。

所以暂定使用第一种方法,typeface使用单例,需要时设置字体。

我个人觉得第一种还是个体力活,而且到后来,这个代码重复率还是非常高的,这又违背了DRY原则。

在地铁上的时候,突然想到DI(Dependency Inject)。已经有一些DI的框架,如ButterKnife,那写出来应该是这样:

1
@CustomFont(R.id.textView) TextView textView 

or

1
2
@InjectView(id=R.id.textView, customFont=true) View anyView @InjectView(id=R.id.textView, customFont=true, font="fonts/ltfz.ttf") View anyView 

这样写出来代码相比重复写setTypeface要好一些。

目前我们的项目还没有使用这类DI框架,等以后引入了,使用第二种注入,写起来应该是很爽的。

保持更新。

参考

  • DI框架
  • ButterKnife

Android:更好的自定义字体方案相关推荐

  1. android字体好看,Android:更好的自定义字体方案

    摘要: 在一个应用中,我需要在所有的UI组件中使用客户提供的字体.这听起来似乎是个很稀松平常的任务,不是吗?是的,我当时也是这么想的.然后我震惊了,Android竟然没有提供一个简单优雅的方式来做这件 ...

  2. android studio 自定义字体,Android Studio中的自定义字体

    如何在android studio中创建自定义字体? 我试图使用自定义字体,我读过,我想将字体放在资产/字体. 我已经搜索了很长时间,但很难找到帮助. 我哪里错了?我真的不知道该怎么做. 我写下了所有 ...

  3. 解析android多语言与自定义字体

    一.android多语言 这里以汉语 英文 印尼文为例记录一下实现流程 1.1,value文件夹下添加不同语言的String.xml文件,分别是 values默认 <resources>& ...

  4. android 开发app使用自定义字体

    在Android中是可以在开发app的时候使用自定义字体的. 在开发app的时候,界面可能要使用到第三方的字体,这时候就需要执行如下操作: 1.在项目中创建font文件夹,存放第三方字体的ttf文件 ...

  5. android的自定义字体,Android 自定义字体方案

    在应用中需要配置不同的字体,而 Android 只能在 xml 中配置系统默认提供的四种字体,需要自定义的字体都需要在 Java 代码中配置. Android 默认方案 你可以通过ID查找到View, ...

  6. 用html修改游戏聊天字体,前端使用自定义字体方案

    工作中我相信大家都遇到过设计要求使用一些奇奇怪怪字体的需求,然后因为字体文件太大,选择切图. 我这个需求就厉害了,用户发的文章可以选择字体.这文章中可以出现的字就太多了,显然上个方案就不合适了,那我们 ...

  7. android使用艺术字,自定义字体

    下面是我自己写的Demo出来的效果! 具体操作步骤也比较简单,先建一个assets文件夹,如下图 接下来把字体库拷贝到asstes中,字体库有需要的话可以给我发邮件,我的qq邮箱:956431651@ ...

  8. android xml黑体字_Android中快速实现自定义字体!

    前言:我们都知道,Android中默认的字体是黑体,而大多数app也都是使用的这种字体,但我们发现,大多数app中,个别地方字体非常好看,例如app的标题栏,菜单栏等地方,那他们是怎么做到的呢?有两种 ...

  9. Android工具栏中心标题和自定义字体

    本文翻译自:Android toolbar center title and custom font I'm trying to figure out the right way to use a c ...

最新文章

  1. Hibernate-ORM:05.Hibernate中的list()和iterator()
  2. boost::container模块实现节点句柄的测试程序
  3. SAP Spartacus PagelayoutComponent里的template
  4. python运算符号输入_【Python】【运算符】
  5. CentOS7 下调教mysql记实 之一
  6. 多线程创建方式 线程池、Future和CompletableFuture
  7. LeetCode 650. 只有两个键的键盘(DP)
  8. Android 系统(257)---Launcher显示未读通知的数量
  9. 每个人都应该读一读贝索斯的致股东信 1997-2016
  10. 华为ensp命令大全_电脑网络:华为交换机基础知识及基本命令配置大全,新手的福音...
  11. Android AnimatedVectorDrawable
  12. mysql图书管理系统设计答辩_基于微信的图书管理系统毕业论文+任务书+开题报告+答辩PPT+前后台(Java+Mysql)源码及数据库文件...
  13. 系统分析与设计方法---结构化分析与设计
  14. 机器学习与网络安全(一)
  15. 新手如何在Git Hub上学习开源项目+社交
  16. 减少计算机视觉效果可以减少游戏卡顿吗,Win10玩游戏更流畅的几招优化方法(亲测有效)...
  17. 考研数学汤家凤 暑期答疑合集
  18. css使两个盒子并列_CSS常见面试题
  19. 人生感悟:欲望适度则为利,欲望过度则为害,高级java开发工程师简历
  20. 好用的Google浏览器插件

热门文章

  1. python自带intertool模块找不到_Python itertools模块详解
  2. python散点图拟合曲线如何求拟合_python 拟合曲线并求参
  3. @JsonIgnore和@JsonSerialize 的 区别
  4. linux下文件下载中文,LINUX环境下资源下载中文目录及中文文件名称问题
  5. android焦点动画,Android编程中PopupWindow的用法分析【位置、动画、焦点】
  6. excel删除重复数据保留一条_Excel一键删除重复数据,你居然还用逐条排查?
  7. Navicat连接oracle03135,ORA-03135: connection lost contact的解决方法
  8. html刘海屏高度,iphone刘海屏网页适配方法
  9. select count(*) from返回值_MySQL 优化:count(1)真的比count(*)快吗
  10. python webservices_python实现webservices接口并调用