最近在做车联网的产品,主打的是语音交互和导航功能,UI给的导航界面可真是够酷炫的。但麻烦的事情也来了,里面的一句话居然用到了三种字体。界面如图所示:

从图中可以看出 500m左前方行驶 居然使用了三种字体,数字一种、英文一种、汉字一种,(这里不讨论拆分三个textview能不能实现的问题,如果能实现也是最迫不得已的办法,何况你解决了这个,上面那个 -2h30m 你要拆成4个textview吗?显然这不合理)我们知道spannableString是个 很强大的类,可以通过new typefacespan(family)设置字体,但他们支持的是系统的三种字体,但我还从没有使用过自定义的字体。为了解决这个问题我仔细看了关于spannableString的介绍。然而这类文章真的不多,只是从一篇文章中得知可以通过自定义typefacespan来使用自定义字体。(文章地址:http://www.cnblogs.com/jisheng/archive/2013/01/10/2854088.html)

如何自定义typefacespan,这东西也没别人做过先例,无奈只好自己去看源码:

 /*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package android.text.style; import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils; /**
* Changes the typeface family of the text to which the span is attached.
*/
public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
private final String mFamily; /**
* @param family The font family for this typeface. Examples include
* "monospace", "serif", and "sans-serif".
*/
public TypefaceSpan(String family) {
mFamily = family;
} public TypefaceSpan(Parcel src) {
mFamily = src.readString();
} public int getSpanTypeId() {
return TextUtils.TYPEFACE_SPAN;
} public int describeContents() {
return 0;
} public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mFamily);
} /**
* Returns the font family name.
*/
public String getFamily() {
return mFamily;
} @Override
public void updateDrawState(TextPaint ds) {
apply(ds, mFamily);
} @Override
public void updateMeasureState(TextPaint paint) {
apply(paint, mFamily);
} private static void apply(Paint paint, String family) {
int oldStyle; Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
} Typeface tf = Typeface.create(family, oldStyle);
int fake = oldStyle & ~tf.getStyle(); if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
} if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
} paint.setTypeface(tf);
}
}

从源码中我们可以看到构造函数(36~38行)传入了一个family的字符串,这个是用来找系统字体的,然后我们往下看,哪里用到了这个family(83行):

我们通过Typeface.create(family,oldStyle)得到了一个typeface,然后从86~92行是设置粗体和斜体。也就是说这个地方才是设置字体的真谛。而我们知道可以通过读取文件的方式得到自定义的typeface,因此完全可以通过掉包的方式实现自定义字体。于是我仿照Typefacespan实现了自己的一个MyTypefaceSpan的类,如下:

 package com.justenjoy.view;

 import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan; /**
* 类名:MyTypefaceSpan <br/>
* 作者 :王洪贺 <br/>
* 描述: <br/>
* 2015年7月15日
*/
public class MyTypefaceSpan extends MetricAffectingSpan { private final Typeface typeface; public MyTypefaceSpan(final Typeface typeface) {
this.typeface = typeface;
} @Override
public void updateDrawState(final TextPaint drawState) {
apply(drawState);
} @Override
public void updateMeasureState(final TextPaint paint) {
apply(paint);
} private void apply(final Paint paint) {
final Typeface oldTypeface = paint.getTypeface();
final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0;
final int fakeStyle = oldStyle & ~typeface.getStyle();
if ((fakeStyle & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fakeStyle & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(typeface);
} }

使用方法也很简单,之前的TypefaceSpan不是传family吗?咱这个传typeface就可以了。为了方便使用,我做了一个单例,因为字体文件在一个程序中会多次使用,使用的时候放到内存中还是比较好的,公共类如下:

 package com.justenjoy.util;

 import com.justenjoy.view.MyTypefaceSpan;

 import android.content.Context;
import android.graphics.Typeface; /**
* 类名:FontsUtil <br/>
* 作者 :王洪贺 <br/>
* 描述:获取自定义字体typefacespan的单例 <br/>
* 2015年7月15日
*/
public class FontsUtil { public static FontsUtil fontsUtil; private Context mContext;
private static Typeface numTypeface;
private static Typeface charTypeface; public FontsUtil(Context context) {
this.mContext = context;
// 字体资源放在内存中,避免反复读取浪费资源
numTypeface = Typeface.createFromAsset(mContext.getAssets(),
"fonts/290-CAI978.ttf");
charTypeface = Typeface.createFromAsset(mContext.getAssets(),
"fonts/048-CAT978.ttf"); } /**
* <br/>
* 概述:字体单例,避免反复读取 <br/>
*
* @param context
* <br/>
* @return
*/
public static FontsUtil getInstance(Context context) {
if (fontsUtil == null) {
fontsUtil = new FontsUtil(context);
}
return fontsUtil;
} /**
* <br/>
* 概述:获取英文字母的字体typefacespan <br/>
*
* @param context
* <br/>
* @return
*/
public MyTypefaceSpan getMyCharTypefaceSpan() {
return new MyTypefaceSpan(charTypeface);
} /**
* <br/>
* 概述:获取数字的字体typefacespan <br/>
*
* @param context
* <br/>
* @return
*/
public MyTypefaceSpan getMyNumTypefaceSpan() {
return new MyTypefaceSpan(numTypeface);
} }

在spannableString的使用就是:

spannableString.setSpan(FontsUtil.getInstance(this).getMyNumTypefaceSpan(), 0, stringsize,Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

其中的两个字体文件是数字和英文的自定义字体,我就不上传了。有什么不明白可以联系我的qq或者邮箱,留言也可以。

我的github地址:https://github.com/dongweiq/study

欢迎关注,欢迎star o(∩_∩)o 。有什么问题请邮箱联系 dongweiqmail@gmail.com qq714094450

(原创)如何在spannableString中使用自定义字体的更多相关文章

  1. WebFont技术使用之如何在app中使用自定义字体

    参考 H5自定义字体解决方法(mark) 移动Web字体的使用 [原]移动web页面使用字体的思考 CSS @font-face规则 引用外部服务器字体

  2. [原创]如何在Parcelable中使用泛型

    [原创]如何在Parcelable中使用泛型 实体类在实现Parcelable接口时,除了要实现它的几个方法之外,还另外要定义一个静态常量CREATOR,如下例所示: public static cl ...

  3. 如何在Axure中使用FontAwesome字体图标

    Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小.颜色.阴影或者其它任何支持的效果. FontAwesome应用在web网页开发中非常方便, ...

  4. 详解如何在Laravel中增加自定义全局函数

    http://www.php.cn/php-weizijiaocheng-383928.html 如何在Laravel中增加自定义全局函数?在我们的应用里经常会有一些全局都可能会用的函数,我们应该怎么 ...

  5. Android 中使用自定义字体的方法

    1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . <?xml version="1.0 ...

  6. 如何在Qt中使用自定义数据类型

    这里我们使用下面这个struct来做说明(这里不管是struct还是class都一样): struct Player { int number; QString firstName; QString ...

  7. css3中的自定义字体

    自定义字体 /*定义*/ @font-face { font-family: "icons"; src: url("icomoon.eot"); src: lo ...

  8. 如何在SharePoint2010中创建自定义电子邮件警报处理程序

    字段,如项目名称字段中,将被截断到的电子邮件通知中的 70 个字符.要解决 70 个字符的限制,请使用"更多信息"一节中的介绍的方法. 要嵌入电子邮件通知中的其他内容. 您想要更改 ...

  9. iOS中使用自定义字体

    1.确定你的项目工程的Resources下有你要用的字体文件(.ttf或者.odf). 2.然后在你的工程的Info.plist文件中新建一行,添加key为:UIAppFonts,类型为Array或D ...

随机推荐

  1. SSH框架中配置Hibernate使用proxool连接池

    一.导入proxool.jar包 案例用的是proxool-0.8.3.jar,一般通过MyEclipse配置的SSH都会包含这个jar,如果没有,就去网上搜下下载导入就好了. 二.新建Proxool ...

  2. JAVA实现word doc docx pdf excel的在线浏览 - 仿百度文库 源码

    我们具体实现思路是这样的 首先下载并安装openoffice和swftools openoffice下载地址:http://www.openoffice.org/download/index.html ...

  3. 如何查看自己运行ubuntu是32位还是64位

    当安装ubuntu在pc上,不推荐在32位pc安装64位操作系统,64位pc安装32位操作系统 方法/步骤 按ctrl+shift+t 快捷键,打开终端,输入sudo uname --m ,按下ent ...

  4. rails3 Bundle简介

    Rails 3开始使用bundle来管理项目的gem依赖.该命令只在一个含有Gemfile的目录下执行. Gemfile: Rails 项目所有的依赖包都在这里配置,不像以前通过require来查找 ...

  5. INCOIN Importing Multilingual Items (Doc ID 278126.1)

    APPLIES TO: Oracle Inventory Management - Version: 11.5.9 to 11.5.10.CU2 - Release: 11.5 to 11.5 GOA ...

  6. 【转】基本数据持久性(一) 使用plist保存和读取数据

    原文网址:http://www.it165.net/pro/html/201309/7170.html 想保存成绩.记录得分.保存账号密码等等?数据持久性可以做到这一点!这篇文章通过简单的程序,来分享 ...

  7. 都说ConcurrentDictionary<TKey, TValue>有陷阱

    看这么几句解释(英文原帖): private static void ConcurrentDictionary() { var dict = new ConcurrentDictionary<i ...

  8. POJ 1655 Balancing Act (求树的重心)

    求树的重心,直接当模板吧.先看POJ题目就知道重心什么意思了... 重心:删除该节点后最大连通块的节点数目最小 #include<cstdio> #include<cstring&g ...

  9. Android 多线程 异步加载

    Android 应用中需要显示网络图片时,图片的加载过程较为耗时,因此加载过程使用线程池进行管理, 同时使用本地缓存保存图片(当来回滚动ListView时,调用缓存的图片),这样加载和显示图片较为友好 ...

  10. HIbernate学习笔记(一) 了解hibernate并搭建环境建立第一个hello world程序

    Hibernate是一个开放源代码的ORM(对象关系映射)框架,它对JDBC进行了轻量级的封装,Java程序员可以使用面向对象的编程思维来操纵数据库,它通过对象属性和数据库表字段之间的映射关系,将对象 ...