(原创)如何在spannableString中使用自定义字体
最近在做车联网的产品,主打的是语音交互和导航功能,UI给的导航界面可真是够酷炫的。但麻烦的事情也来了,里面的一句话居然用到了三种字体。界面如图所示:
从图中可以看出 500m左前方行驶 居然使用了三种字体,数字一种、英文一种、汉字一种,(这里不讨论拆分三个textview能不能实现的问题,如果能实现也是最迫不得已的办法,何况你解决了这个,上面那个 -2h30m 你要拆成4个textview吗?显然这不合理)我们知道spannableString是个 很强大的类,可以通过new typefacespan(family)设置字体,但他们支持的是系统的三种字体,但我还从没有使用过自定义的字体。为了解决这个问题我仔细看了关于spannableString的介绍。然而这类文章真的不多,只是从一篇文章中得知可以通过自定义typefacespan来使用自定义字体。(文章地址:http://www.cnblogs.com/jisheng/archive/2013/01/10/2854088.html)
如何自定义typefacespan,这东西也没别人做过先例,无奈只好自己去看源码:
1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.text.style; 18 19 import android.graphics.Paint; 20 import android.graphics.Typeface; 21 import android.os.Parcel; 22 import android.text.ParcelableSpan; 23 import android.text.TextPaint; 24 import android.text.TextUtils; 25 26 /** 27 * Changes the typeface family of the text to which the span is attached. 28 */ 29 public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan { 30 private final String mFamily; 31 32 /** 33 * @param family The font family for this typeface. Examples include 34 * "monospace", "serif", and "sans-serif". 35 */ 36 public TypefaceSpan(String family) { 37 mFamily = family; 38 } 39 40 public TypefaceSpan(Parcel src) { 41 mFamily = src.readString(); 42 } 43 44 public int getSpanTypeId() { 45 return TextUtils.TYPEFACE_SPAN; 46 } 47 48 public int describeContents() { 49 return 0; 50 } 51 52 public void writeToParcel(Parcel dest, int flags) { 53 dest.writeString(mFamily); 54 } 55 56 /** 57 * Returns the font family name. 58 */ 59 public String getFamily() { 60 return mFamily; 61 } 62 63 @Override 64 public void updateDrawState(TextPaint ds) { 65 apply(ds, mFamily); 66 } 67 68 @Override 69 public void updateMeasureState(TextPaint paint) { 70 apply(paint, mFamily); 71 } 72 73 private static void apply(Paint paint, String family) { 74 int oldStyle; 75 76 Typeface old = paint.getTypeface(); 77 if (old == null) { 78 oldStyle = 0; 79 } else { 80 oldStyle = old.getStyle(); 81 } 82 83 Typeface tf = Typeface.create(family, oldStyle); 84 int fake = oldStyle & ~tf.getStyle(); 85 86 if ((fake & Typeface.BOLD) != 0) { 87 paint.setFakeBoldText(true); 88 } 89 90 if ((fake & Typeface.ITALIC) != 0) { 91 paint.setTextSkewX(-0.25f); 92 } 93 94 paint.setTypeface(tf); 95 } 96 }
从源码中我们可以看到构造函数(36~38行)传入了一个family的字符串,这个是用来找系统字体的,然后我们往下看,哪里用到了这个family(83行):
我们通过Typeface.create(family,oldStyle)得到了一个typeface,然后从86~92行是设置粗体和斜体。也就是说这个地方才是设置字体的真谛。而我们知道可以通过读取文件的方式得到自定义的typeface,因此完全可以通过掉包的方式实现自定义字体。于是我仿照Typefacespan实现了自己的一个MyTypefaceSpan的类,如下:
1 package com.justenjoy.view; 2 3 import android.graphics.Paint; 4 import android.graphics.Typeface; 5 import android.text.TextPaint; 6 import android.text.style.MetricAffectingSpan; 7 8 /** 9 * 类名:MyTypefaceSpan <br/> 10 * 作者 :王洪贺 <br/> 11 * 描述: <br/> 12 * 2015年7月15日 13 */ 14 public class MyTypefaceSpan extends MetricAffectingSpan { 15 16 private final Typeface typeface; 17 18 public MyTypefaceSpan(final Typeface typeface) { 19 this.typeface = typeface; 20 } 21 22 @Override 23 public void updateDrawState(final TextPaint drawState) { 24 apply(drawState); 25 } 26 27 @Override 28 public void updateMeasureState(final TextPaint paint) { 29 apply(paint); 30 } 31 32 private void apply(final Paint paint) { 33 final Typeface oldTypeface = paint.getTypeface(); 34 final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0; 35 final int fakeStyle = oldStyle & ~typeface.getStyle(); 36 if ((fakeStyle & Typeface.BOLD) != 0) { 37 paint.setFakeBoldText(true); 38 } 39 if ((fakeStyle & Typeface.ITALIC) != 0) { 40 paint.setTextSkewX(-0.25f); 41 } 42 paint.setTypeface(typeface); 43 } 44 45 }
使用方法也很简单,之前的TypefaceSpan不是传family吗?咱这个传typeface就可以了。为了方便使用,我做了一个单例,因为字体文件在一个程序中会多次使用,使用的时候放到内存中还是比较好的,公共类如下:
1 package com.justenjoy.util; 2 3 import com.justenjoy.view.MyTypefaceSpan; 4 5 import android.content.Context; 6 import android.graphics.Typeface; 7 8 /** 9 * 类名:FontsUtil <br/> 10 * 作者 :王洪贺 <br/> 11 * 描述:获取自定义字体typefacespan的单例 <br/> 12 * 2015年7月15日 13 */ 14 public class FontsUtil { 15 16 public static FontsUtil fontsUtil; 17 18 private Context mContext; 19 private static Typeface numTypeface; 20 private static Typeface charTypeface; 21 22 public FontsUtil(Context context) { 23 this.mContext = context; 24 // 字体资源放在内存中,避免反复读取浪费资源 25 numTypeface = Typeface.createFromAsset(mContext.getAssets(), 26 "fonts/290-CAI978.ttf"); 27 charTypeface = Typeface.createFromAsset(mContext.getAssets(), 28 "fonts/048-CAT978.ttf"); 29 30 } 31 32 /** 33 * <br/> 34 * 概述:字体单例,避免反复读取 <br/> 35 * 36 * @param context 37 * <br/> 38 * @return 39 */ 40 public static FontsUtil getInstance(Context context) { 41 if (fontsUtil == null) { 42 fontsUtil = new FontsUtil(context); 43 } 44 return fontsUtil; 45 } 46 47 /** 48 * <br/> 49 * 概述:获取英文字母的字体typefacespan <br/> 50 * 51 * @param context 52 * <br/> 53 * @return 54 */ 55 public MyTypefaceSpan getMyCharTypefaceSpan() { 56 return new MyTypefaceSpan(charTypeface); 57 } 58 59 /** 60 * <br/> 61 * 概述:获取数字的字体typefacespan <br/> 62 * 63 * @param context 64 * <br/> 65 * @return 66 */ 67 public MyTypefaceSpan getMyNumTypefaceSpan() { 68 return new MyTypefaceSpan(numTypeface); 69 } 70 71 }
在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中使用自定义字体相关推荐
- android studio 自定义字体,Android Studio中的自定义字体
如何在android studio中创建自定义字体? 我试图使用自定义字体,我读过,我想将字体放在资产/字体. 我已经搜索了很长时间,但很难找到帮助. 我哪里错了?我真的不知道该怎么做. 我写下了所有 ...
- 如何在 HTML中使用图标字体
1. 推荐 首先推荐一个下载图标字体的网址:https://icomoon.io/app/#/select 还有一个阿里巴巴矢量图标库:http://www.iconfont.cn/ (操作稍微复杂 ...
- 在iPhone App中使用自定义字体
如何在iPhone程序中使用自定义字体?比如要添加方正兰亭字体,首先需要一个ttf的字体库.到一些字体库的网站上去下载吧 然后把这个文件添加到工程里面 在plist里面添加 添加成功后,就可以使用啦 ...
- 如何在 Word 中使用自定义样式生成文章目录
如何在 Word 中使用自定义样式生成文章目录 概要 本文介绍如何在 Microsoft Word 2002 和 Microsoft Office Word 2003 中使用自定义样式创建目录.在 W ...
- html页面调用ico图标,如何在HTML中使用图标字体 - icon font?
日期:2012-8-27 来源:GBin1.com 在线演示 本地下载 主要特性 使用icon font来生成图标相对于基于图片的图标来说,有如下的好处: 自由的变化大小 自由的修改颜色 添加阴影 ...
- 如何在android中创建自定义对话框?
本文翻译自:How to create a Custom Dialog box in android? I want to create a custom dialog box like below ...
- hive 元数据 自定义_如何在Hive中创建自定义函数UDF及如何直接通过Impala的同步元数据重用UDF的jar文件-阿里云开发者社区...
如何在Hive中创建自定义函数UDF及使用 如何在Impala中使用Hive的自定义函数 UDF函数开发 使用Intellij工具开发Hive的UDF函数,进行编译: 1.使用Intellij工具通过 ...
- dota2html颜色代码,技术向教程 如何在DotA2中使用彩色字体
技术向教程 如何在DotA2中使用彩色字体 编译:M82A1炸菜 如何使用16进制编辑器对DotA2文字就行颜色编辑 需要:十六进制编辑器.记事本.控制台 1.打开steam平台 2.在游戏库中选择D ...
- android 使用 系统字体,Android_解析Android中使用自定义字体的实现方法,1、Android系统默认支持三种字 - phpStudy...
解析Android中使用自定义字体的实现方法 1.Android系统默认支持三种字体,分别为:"sans", "serif", "monospace ...
最新文章
- c++后台管理系统_【获奖案例】第三届全国医院物联网大会“中国医院物联网应用十大优秀案例”安徽医科大学第一附属医院手术室行为管理系统...
- linux服务器的功能需求,Linux下的各种服务器技术及配置 (毕业论文).doc
- VTK:椭圆圆柱用法实战
- ansible(3)——主机列表,ssh,公钥私钥
- 使用Spring Reactor Core进行分散收集
- cocos2d-x学习之自动内存管理
- 将数据从MySql导入数据至SQL Server 2000
- unity3d的uGUI基本操作
- axure文本框添加水印_Axure教程:限制输入框输入字数
- angularjs 笔记(1) -- 引导
- c语言题库南信,c语言上机题库百科园南信大.docx
- androidx中app.startup组件官方指南
- 中国人口总数、老龄人口占比及2040人口年龄结构变化预测
- 202010118——MML命令
- EXCEL VBA 之录制宏
- 太虚幻境 文/江湖一劍客
- 10-38 A4-7在订单详细信息表中查找包含产品种类数超过特定值的订单信息 (20 分)
- 如何改变this指向?
- 端到端的文本无关说话人确认的深度神经网络嵌入
- iMindMap思维导图软件之树状思维导图