当前位置:   article > 正文

Android进阶之路 - 深入浅出字体、字体库_android 字体

android 字体

当时组内临时接到一个换字体库的需求,这个需求相对简单,因为手头有其他事情,同时之前也没换过字体库,就交给了同事去做了;现在有时间就好好充实下自己 ( 我写的也未必全对,如有不足可直接提出,相互探讨)

在正式开始以前,你首先需要告知产品经理和设计师,因为引入新的字体库存在版权问题,需要对方授权方可使用,否则涉及侵权;如果产品确定一定要改的话,请产品和设计提供相关字体库

开篇前没想到写一篇基础版的字体库相关内容,用了小俩天时间,越写越多,也参考了十几篇blog,有新有旧,希望该篇对你有所帮助

Look:不知道你在看此篇时,是否有了解过字体库相关内容,我先行说一下,我在求知中遇到的问题

Android的默认字体到底是什么?为什么有的说是 Source Han Sans(思源),有的说是 Roboto,有的说是 DroidSans、DroidSansFallback

关于这个问题,我翻了一堆文章,答案都东拼西凑、大同小异,并没有一个比较完善的解释,最后还是去外面找到一个合理的解释,我来统一整合一下吧(Hint:如果你想了解更多,也有一些个人兴趣,可前往基础认知中继续了解下,欢迎探讨~)

首先 Source Han Sans(思源)RobotoDroidSans、DroidSansFallback 字体、字体库都是存在的,且都是存在于Android系统中的!

其中 Source Han Sans(思源) 适用于中文环境 & 中日韩三国,Roboto适用于英文&数字, DroidSans、DroidSansFallback适用于中日韩以外的国家 或 作为备用(默认)字体;(故知道国内用的是思源字体库+Roboto字体库即可

业务需求&实现

引入、以及使用新的字体库,都很简单,如果只是为了实现业务需要的话,只看该段即可;如果有兴趣,且时间充足的话可以大致过一下~

业务需求

因为是UI的设计需求,我们主要看设计图相关数据信息即可

UI效果图

在这里插入图片描述

font-family(字体库): Roboto-Medium;

在这里插入图片描述

Hint:根据设计图可以看出使用到的主要是 Roboto字体中的 中等加粗字体

业务实现

关于字体库业务的实现方式,我看了一下实现方式,主要有静态实现(xml)和动态实现(代码设置),具体使用哪种方式取决于自己和业务场景的使用

因为俩种先方式针对于字体库的存储位置有所不同,故开设求知小课堂简单说明res、assets同异

相同点:两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制

不同点:

  • 引用资源的方式不同:res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
  • 处理方式不同
  • 子目录不同:res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹

根据涉及提供的字体库,解压后放在AndroidStudio内可以直接看预览效果

在这里插入图片描述

综合实现效果

俩种实现方式的效果是统一的,只是静态实现支持预览,故统一效果图;

视图效果分别对应以下三类(我其实看不出太大区别,可能只有设计比较容易辨别)

  • 默认字体
  • Roboto 普通字体
  • Roboto 加粗字体
    在这里插入图片描述
静态实现

静态实现的优势在于使用方便,可以直接设置属性,同时支持直接观察设置效果;不足之处在于产品要求某些业务场景,需要动态切换控件的字体效果(千人千面)

  1. res - 创建 font 文件夹用于存放字体库
    在这里插入图片描述
  2. 关于字体库的命令需要符合命名规范(对比动态实现命名有所不同)

错误命名

在这里插入图片描述

正确使用

1

xml 中引用字体库

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:text="0.00" />

    <TextView
        android:id="@+id/tv_text1"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:fontFamily="@font/roboto_regular"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="0.08" />

    <TextView
        android:id="@+id/tv_text2"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:fontFamily="@font/roboto_medium"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="66.66" />

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

预览效果

在这里插入图片描述

动态实现

动态实现的方式同静态实现稍有不同,首先是资源存储的地方,其次是设置字体库的方式

  1. 创建assets文件夹
    在这里插入图片描述
    AndroidStudio 会自动提示
    在这里插入图片描述
  2. assets 文件夹下创建 fonts 文件夹,主要用于存储字体库
    在这里插入图片描述
  3. 字体库一般为 ttf 文件,我们将字体与放置于此即可,总体如下
    在这里插入图片描述

调用方式

常规设置

package com.example.kotlindemo

import android.annotation.SuppressLint
import android.graphics.Typeface
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.want_text_display)

        var t1 = findViewById<TextView>(R.id.tv_text1)
        val regular = Typeface.createFromAsset(assets,"fonts/Roboto-Regular.ttf")
        t1.typeface = regular;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

单控件一般采用同一个字体库样式,这里是俩个控件的设置方式(设置方式相同),只所以多写一份是因为我引用了俩个字体库的样式,一个为roboto普通字体,一个为roboto加粗字体

package com.example.kotlindemo

import android.annotation.SuppressLint
import android.graphics.Typeface
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.want_text_display)

        var t1 = findViewById<TextView>(R.id.tv_text1)
        var t2 = findViewById<TextView>(R.id.tv_text2)

        val regular = Typeface.createFromAsset(assets,"fonts/Roboto-Regular.ttf")
        val medium = Typeface.createFromAsset(assets,"fonts/Roboto-Medium.ttf")

        t1.typeface = regular;
        t2.typeface = medium;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

want_text_display

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:text="0.00" />

    <TextView
        android:id="@+id/tv_text1"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="0.08" />

    <TextView
        android:id="@+id/tv_text2"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="66.66" />

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

留作备忘

我之前翻了一篇blog,看到说要设置ElegantTextHeight属性,否则高度会发生变化,但是我并未遇到相关场景,故再次留作备忘

// 应用字体
var typeFace = Typeface.createFromAsset(mContext.getAssets(),"fonts/sourcehanserifcn_regular.otf")
//这个不可缺少,不加tvtext高度变大很多  很不美观
tvtext.setElegantTextHeight(true)
tvtext.setTypeface(typeFace)
  • 1
  • 2
  • 3
  • 4
  • 5

基础认知

Android 拥有着属于自己的默认字体库,不过因为国内厂商较多,大多都会定制化字体,所以显示效果各有不同,大多数时候字体并未完全统一

针对于我们常见的中文、英文、数字使用的字体库也有所不同

Android 默认字体

  • 中文字体:Source Han Sans / Noto(思源黑体)

维基百科:思源黑体(英语:Source Han Sans,“思源”一词来自于成语“饮水思源”)是Adobe与Google所领导开发的开源字体家族,1.001及更早版本以Apache 2.0许可证许可,而1.002及更新版本则使用SIL开源字体授权,属于无衬线黑体。思源黑体于2014年7月16日首次发布,支持繁体中文、简体中文、日文及韩文,并且各有7种字体粗细。公开之时为当时涵盖字符数量最多的字体,44,666 个字符分属于 65,535 个字形中,此为OpenType字体技术的极限。

  • 数字&英文字体:Roboto

小课堂

DroidSansFallback思源黑体是两种不同的字体,它们在 Android 系统中具有不同的作用和应用场景。

DroidSansFallbackDroidSansFallback 是 Android 系统中的一个字体库,用于支持多语言和字符集的显示。它包含了广泛的 Unicode 字符覆盖范围,包括了一些不常见的字符和语言的字形。当系统无法找到适当的字体来显示特定字符时,它会使用 DroidSansFallback 来作为回退字体。这使得 Android 能够显示多种语言和符号,即使默认字体库(如 Roboto)没有包含对应的字符。

以下是Android安卓系统默认的几种字体:

  • Clockopia.ttf 系统默认待机时钟字体;
  • DroidSansFallback.ttf 系统默认中文字体;
  • DroidSans.ttf 系统默认英文字体;
  • DroidSans-Bold.ttf 系统默认英文粗字体;

思源黑体:思源黑体是一种由 AdobeGoogle 共同开发的开源字体,用于支持中日韩(CJK)语言的显示。它包含了汉字、日文假名和韩文字符,具有广泛的覆盖范围。思源黑体在设计上注重保持字形的清晰度和可读性,同时适应不同的屏幕尺寸和分辨率。在一些中日韩语言环境下,Android 系统会使用思源黑体作为默认的字体来显示相应的文字内容。

不论我们使用哪种字体库,一般字体库都会提供字体的多种样式,例如常规、加粗等,例如 Regular、Italic、Bold、Bold-italic、Light、Light-italic、Thin、Thin-italic、Condensed regular、Condensed italic、Condensed bold、Condensed bold-italic

作为队友,有必要了解下 IOS 默认字体

  • 中文字体:PingFang SC
  • 数字&英文字体:.SF UI Text、.SF UI Display

默默 copy 俩张图

在这里插入图片描述

以中文字体来做对比,可以看出平方对比思源黑体,笔画更细、字怀更大、字体使用弧度更少,偏旁所占字面更小(说实话,还得设计来看,我基本看不出什么太大区别…)。

在这里插入图片描述

关于Roboto字体的一些补充介绍

这部分内容是看百度发的一篇blog借鉴于此的(偏官方简介),仅做了解即可,无需细读,以下介绍均针对于Android客户端

字体特点

  • 清晰的字形:Roboto字体有着非常清晰的字形,这使得它在阅读和书写时非常舒适。
  • 可读性强:Roboto字体具有很好的可读性,这意味着在大多数应用程序中它都能很好地适用。
  • 平衡的间距:Roboto字体在行与行之间的间距上也有很好的平衡。这意味着文本在屏幕上的布局非常均匀,看起来非常整齐。
  • 广泛的可用性:Roboto字体是一种开源字体,因此它在Android开源项目中被广泛使用。这使得它在各种设备和屏幕分辨率上都能很好地适用。

字体优点

  • 看起来专业:使用Roboto字体可以使应用程序看起来更加专业化。它的清晰字形和平衡的间距使得文本在屏幕上看起来更加清晰。
  • 提高可读性:由于Roboto字体的可读性很好,因此在阅读和书写时非常舒适,这也意味着应用程序的可用性得到了提高。
  • 减少屏幕分辨率变化:由于Roboto字体在各种设备和屏幕分辨率上都能很好地适用,因此应用程序在适应不同屏幕大小时不会产生过大的影响。
  • 延长设备电池寿命:一些研究表明,使用Roboto字体可以延长设备电池寿命。这是因为较暗的字体可以减少屏幕亮度的需求,从而减少了电池的消耗。

字体不足

  • 应用程序的可读性降低:如果应用程序中的文本使用了不太一样的字体,那么可能会导致应用程序的可读性降低。
  • 应用程序的可用性降低:如果应用程序中的文本使用了Roboto字体,而设备屏幕分辨率较低,那么可能会导致应用程序的可用性降低。
  • 设备电池消耗增加:有一些研究表明,使用Roboto字体可能会导致设备电池消耗增加。这是因为较暗的字体可能会导致屏幕亮度的需求增加,从而增加了电池的消耗。

厂商字体

Anddroid本身的定制性较强,早期换字体的时候基本上需要root,如今手机自带这个功能,各厂商也有了足够的权限,所以在看到大家对系统默认字体不是很喜欢时,就致力研发自家的字体;针对国内的厂商大多都有自定的字体,例如 MisansOPPO SANSHarmonyOS Sans 等一些手机厂商默认的字体。这些字体不仅支持中文显示,连西文(如英文)都能完美显示。

在一篇文章内看到介绍了 各大手机厂商的默认字体,此处仅做一些关键信息摘要

这位朋友说字体好不好,还需注意这三个方面:字符数要多(照顾部分生僻字)、字重齐全(粗细均匀)、OpenType支持(字符根据情况自动调整,使其看起来更加美观)。

我们来看看主流的这三款字体哪个更好看吧!这里再说明一下,这三款字体都是汉仪定制字体,因此字体不全是手机厂商定制。

小米(Misans)

针对于MIUI13里面宣传的全新系统字体MiSans,全方位优化中英文及数字设计,字形简约,视觉清晰,阅读舒适。

其实这个MiSans算是黑体的变种。虽然也是黑体,但是在一些细节处能看出是真下了功夫

  • 笔型平直有力
  • 设计更加简约
  • 减少视觉负担
  • 更有利于屏幕显示
  • 支持OpenType功能

MiSan一出,尤其是在一些长文和标点符号比较多的场景下,明显所谓的高级感更强,而鸿蒙字体与其相比就显得普通了一些。

华为(HarmonyOS Sans)

  • 支持更多的语言;
  • 对斜体和繁体中文有专门的加强字体;
  • 中英文混排、文字和标点符号混排感觉也是相当优秀,不会出现很生硬的错行,但是字重比小米MiSans要少,只有6种字重。

OPPO(OPPO SANS)

  • 全新骨架
  • 中宫自然舒适
  • 结构稳定
  • 字形舒展
  • 强化了屏幕显示的易读性和美观性

原理兴趣

Android字体工作原理

android字体由android 2D图形引擎skia实现,并在ZygotePreloading classes中对系统字体进行load

相关文件有:skTypeface.cppskFontHost_android.cpp,其中后者是skia针对android平台字体实现的port。主要的变量有:

struct FontInitRec {const char*         
fFileName;const char* const*  fNames;     
// null-terminated list};struct FamilyRec {FamilyRec*  fNext;SkTypeface* fFaces[5];};
//uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];load_system_fonts()@skFontHost_android.cpp 
  • 1
  • 2
  • 3
  • 4

load系统中所有的字体并给每种字体分配唯一的ID,并将字体分为两种:FamilyFontsFallbackFontsskPaint通过应用程序设置的字体(Typeface)所对应的ID最终实现字符的显示。

替换Android默认的汉字字体

android系统中,DroidSans是默认字体,只包含西方字符,应用程序默认情况下都会调用它,而DroidSansFallback包含了东亚字符,当需要显示的字符在DroidSans字体中不存在(如:汉字)时,即没有对应编码的字符时,系统会到DroidSansFallback中去找相应编码的字符,如果找到,则使用DroidSansFallback字体来显示它,如果仍找不到该编码对应的字符,则无法在屏幕上显示该字符。

为android系统添加一种默认字体,类似“sans”,“serif”,“monospace

在android系统中,默认的中文字体只有一种:DroidSansFallback.ttf,如果想在android应用程序中随意设置想要的中文字体,除了在应用程序中通过assets目录引入字体文件外,还可以通过增加android默认字体的方式来实现。添加步骤大致如下:

  1. frameworks/base/data/fonts 目录下添加字体文件,例如 Driod-kaishu.ttf;
  2. skia中增加楷书这一字体,需要修改的文件主要有skFontHost.cpp、skTypeface.cpp、Typeface.java等;
  3. java层添加楷书字体相关API,需要修改的文件主要有typeface.java和textview.java;
  4. 编译SDK
  5. 将新生成的sdk导入项目,可通过setTypeface(Typeface.KAISHU)android:typeface=(“kaishu”)两种方式设置自己添加的字体。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/871855
推荐阅读
相关标签
  

闽ICP备14008679号