Android进阶之路 - 字体加粗,定制化字体粗度

news2025/9/14 18:01:10

在客户端中不论是PC端,还是移动端主要价值之一就体现在用户交互方面,也就是用户体验了,接下来讲的是很常见的字体加粗问题

UI大找茬

  • 深入浅出字体、字体库
  • TextView文本渐变
  • 字体阴影、文字阴影
  • 字体加粗 - 定制化字体粗度

在开发中经常会遇到设计说某个文本字体粗度不对,需要重一点,或者轻一点,这时候当系统控件原属性不满足需求时,就需要我们定制化处理一下

    • 基础讲解
    • 系统自带 - 原始版(粗度固定,无扩展)
    • 自定义控件 - 基础版(扩展不足,基本够用)
      • 优化前
      • 优化后
    • 使用方式
      • 静态设置
      • 动态设置
    • 自定义控件 - 进阶版(推荐:可自行扩展,定制化高)
      • 仅支持动态设置
      • 支持动态、静态设置
        • 静态设置
        • 动态设置

虽然看起来写了不少,但其实核心只在于获取当前控件的 Paint(画笔)后重新设置strokeWidth、style属性 ,然后重新绘制即可!

tip:差点忘记说了,如果通过该篇未满足你的诉求,你可以看一下设计是否使用了字体库,一般字体库也会提供常规字体和加粗字体,关于字体库方面的知识,可以直接前往 深入浅出字体、字体库

基础讲解

设计比较喜欢拿 Android 与 IOS 做对比,所以经常会遇到一些 IOS 分分钟解决的问题,Android 却需要花多倍的时间来处理,以前经常会遇到 1 IOS = 1.5||2 Android 的场景,现在这环境可能比较这样的场景也比较少咯

关于字体粗度的实际设置,主要是在体现其 字重(字体粗细),因字重等级不同,带来的效果也有所不同

Andoird 提供的字体粗度主要有俩种

  • normal 默认正常字体(0)
  • bold 加粗字体(1)

相对于Android 提供的 regular-400bold-700 两种字重(设置600以下均以400字重效果来显示;设置700才会显示出加粗文字)- 源码中常以 0 - 1设置字重 ;iOS系统原生字体字重等级全面,从100-600都有,效果也更全一些,网上找了一个对比图如下

在这里插入图片描述

由于 Andoird 的开源性,在国内有着众多厂商,不同厂商有时候也会设计自已品牌的系统字体包,所以即便是相同的代码,也可能在不同的安卓手机上呈现的效果也可能不相同,因此我们往往需要通过一些自定义控件来尽量保持效果的一致性!


系统自带 - 原始版(粗度固定,无扩展)

AndroidTextViewEditText 提供了 textStyle 属性用于设置字体粗度

  <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:gravity="center"
      android:text="字体粗度"
      android:textStyle="bold" />

实现效果
在这里插入图片描述
在这里插入图片描述

关于 textStyle 属性值,主要提供了以下三种类型

  • normal 默认正常字体
  • bold 加粗字体
  • italic 斜体
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MediumTextView">
        <attr name="mediumState" format="boolean" />
    </declare-styleable>

</resources>

自定义控件 - 基础版(扩展不足,基本够用)

首先在 attr/attrs 添加自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MediumTextView">
        <attr name="mediumState" format="boolean" />
    </declare-styleable>
</resources>

实现效果

在这里插入图片描述

Tip:以下俩种方式均可正常使用,建议使用优化后的减少无效逻辑

优化前

package com.example.boldtext

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSet

class MediumOldTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {

    private var mediumState: Boolean = false

    init {
        val array = context.obtainStyledAttributes(attrs, R.styleable.MediumTextView)
        mediumState = array.getBoolean(R.styleable.MediumTextView_mediumState, false)
        array.recycle()
    }

    override fun onDraw(canvas: Canvas?) {
        if (mediumState) {
            val strokeWidth = paint.strokeWidth
            val style = paint.style
            paint.strokeWidth = 0.6f
            paint.style = Paint.Style.FILL_AND_STROKE
            super.onDraw(canvas)
            paint.strokeWidth = strokeWidth
            paint.style = style
        } else {
            super.onDraw(canvas)
        }
    }

    fun setMediumState(mediumState: Boolean) {
        this.mediumState = mediumState
        requestLayout()
    }

}

优化后

去除一些无用逻辑、代码

package com.example.boldtext


import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSet

class MediumTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {

    private var mediumState: Boolean = false

    init {
        val array = context.obtainStyledAttributes(attrs, R.styleable.MediumTextView)
        mediumState = array.getBoolean(R.styleable.MediumTextView_mediumState, false)
        array.recycle()
    }

    override fun onDraw(canvas: Canvas?) {
        if (mediumState) {
        	//可通过设置该数值改变加粗字重
            paint.strokeWidth = 0.6f
            paint.style = Paint.Style.FILL_AND_STROKE
        }
        super.onDraw(canvas)
    }

    fun setMediumText(mediumText: Boolean) {
        this.mediumState = mediumText
        requestLayout()
//        postInvalidate()
    }

}

使用方式

静态为 xml 设置,动态为代码设置

静态设置

<com.example.boldtext.MediumTextView
    android:id="@+id/medium_view"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:gravity="center"
    android:text="加粗字体"
    app:mediumState="true" />

动态设置

package com.example.boldtext

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mediumView = findViewById<MediumTextView>(R.id.medium_view)
        //设置加粗
        mediumView.setMediumState(true)
    }
}

自定义控件 - 进阶版(推荐:可自行扩展,定制化高)

实现效果

在这里插入图片描述

仅支持动态设置

Tip:假设别的组件也有字体加粗的需求,可以尝试继承该组件

创建 - 自定义组件

package com.example.boldtext

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSet

open class TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    AppCompatTextView(context, attrs, defStyleAttr) {

    private var mTypefaceScale: Float = 0.0f

    enum class TypefaceScale {
        MEDIUM, MEDIUM_SMALL, DEFAULT,
    }

    override fun onDraw(canvas: Canvas?) {
        if (mTypefaceScale == 0f) {
            return super.onDraw(canvas)
        }
        val strokeWidth = paint.strokeWidth
        val style = paint.style
        paint.strokeWidth = mTypefaceScale
        paint.style = Paint.Style.FILL_AND_STROKE
        super.onDraw(canvas)
        paint.strokeWidth = strokeWidth
        paint.style = style
    }

    fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) {
        mTypefaceScale = when (scale) {
            TypefaceScale.DEFAULT -> 0.0f
            TypefaceScale.MEDIUM_SMALL -> 0.6f
            TypefaceScale.MEDIUM -> 1.1f
        }
        postInvalidate()
    }

}

使用方式

package com.example.boldtext

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val typefaceView = findViewById<TypefaceTextView>(R.id.typeface_view)
        //设置加粗
        typefaceView.setTypefaceScale(TypefaceTextView.TypefaceScale.MEDIUM_SMALL)
    }
}

控件引入

    <com.example.boldtext.TypefaceTextView
        android:id="@+id/typeface_view"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="TypefaceTextView 加粗字体" />

扩展:因为我们用的是 splitties 三方的一个布局组件,所以分享、记录一些扩展函数,逐步分析、学习

布局方式

   add(lParams(), typefaceTextView {
       gravity = gravityEnd
       typefaceScale = TypefaceScale.MEDIUM_SMALL
       textSize = 14f
       textColor = "#333333".toColorInt()
   })

add函数 将子布局添加到对应ViewGroup中

import android.view.View
import android.view.ViewGroup


inline fun <V : View> ViewGroup.add(lp: ViewGroup.LayoutParams, view: V): V = view.also { addView(it, lp) }

splitties - lParams 函数

inline fun LinearLayout.lParams(
    width: Int = wrapContent,
    height: Int = wrapContent,
    initParams: LinearLayout.LayoutParams.() -> Unit = {}
): LinearLayout.LayoutParams {
    contract { callsInPlace(initParams, InvocationKind.EXACTLY_ONCE) }
    return LinearLayout.LayoutParams(width, height).apply(initParams)
}

inline fun LinearLayout.lParams(
    width: Int = wrapContent,
    height: Int = wrapContent,
    gravity: Int = -1,
    weight: Float = 0f,
    initParams: LinearLayout.LayoutParams.() -> Unit = {}
): LinearLayout.LayoutParams {
    contract { callsInPlace(initParams, InvocationKind.EXACTLY_ONCE) }
    return LinearLayout.LayoutParams(width, height).also {
        it.gravity = gravity
        it.weight = weight
    }.apply(initParams)
}

View - typefaceTextView 函数

// TypefaceTextView 防苹果系统的字体加粗------------------------------------------------------------------
inline fun Context.typefaceTextView(
    @IdRes id: Int = View.NO_ID,
    @StyleRes theme: Int = NO_THEME,
    initView: TypefaceTextView.() -> Unit = {}
): TypefaceTextView {
    return view(::TypefaceTextView, id, theme, initView)
}

inline fun View.typefaceTextView(
    @IdRes id: Int = View.NO_ID,
    @StyleRes theme: Int = NO_THEME,
    initView: TypefaceTextView.() -> Unit = {}
): TypefaceTextView {
    return context.typefaceTextView(id, theme, initView)
}

inline fun Ui.typefaceTextView(
    @IdRes id: Int = View.NO_ID,
    @StyleRes theme: Int = NO_THEME,
    initView: TypefaceTextView.() -> Unit = {}
): TypefaceTextView {
    return ctx.typefaceTextView(id, theme, initView)
}
// -------------------------------------------------------------------------------------------------------

typefaceTextView - typefaceScale 加粗类型函数

enum class TypefaceScale {
//    MEDIUM,
    MEDIUM_SMALL,
    DEFAULT,
}

var TypefaceTextView.typefaceScale: TypefaceScale
    @Deprecated(NO_GETTER, level = DeprecationLevel.HIDDEN) get() = noGetter
    set(value) {
        val scale = when (value) {
//            TypefaceScale.MEDIUM -> TypefaceTextView.TypefaceScale.MEDIUM
            TypefaceScale.MEDIUM_SMALL -> TypefaceTextView.TypefaceScale.MEDIUM_SMALL
            TypefaceScale.DEFAULT -> TypefaceTextView.TypefaceScale.DEFAULT
        }
        setTypefaceScale(scale)
    }

支持动态、静态设置

为了方便直接在 xml 中使字体加粗,需要在控件上引入自定义属性,故需添加以下属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TypefaceTextView">
        <attr name="fontScale" format="enum">
            <enum name="normal" value="0" />
            <enum name="medium" value="1" />
            <enum name="bold" value="2" />
        </attr>
    </declare-styleable>
</resources>

创建 - 自定义组件

package com.example.boldtext

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSet

class TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    AppCompatTextView(context, attrs, defStyleAttr) {

    private var mTypefaceScale: Float = 0.0f

    init {
        if (attrs != null) {
            val array = context.obtainStyledAttributes(attrs, R.styleable.TypefaceTextView)
            val typefaceScale = array.getInt(R.styleable.TypefaceTextView_fontScale, 0)
            mTypefaceScale = when (typefaceScale) {
                1 -> 0.6f
                2 -> 1.1f
                else -> 0.0f
            }
            array.recycle()
        }
    }

    enum class TypefaceScale {
        MEDIUM, DEFAULT, BOLD
    }

    override fun onDraw(canvas: Canvas?) {
        if (mTypefaceScale == 0f) {
            return super.onDraw(canvas)
        }
        val strokeWidth = paint.strokeWidth
        val style = paint.style
        paint.strokeWidth = mTypefaceScale
        paint.style = Paint.Style.FILL_AND_STROKE
        super.onDraw(canvas)
        paint.strokeWidth = strokeWidth
        paint.style = style
    }

    internal fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) {
        mTypefaceScale = when (scale) {
            TypefaceScale.DEFAULT -> 0.0f
            TypefaceScale.MEDIUM -> 0.6f
            TypefaceScale.BOLD -> 1.1f
        }
        invalidate()
    }

}
静态设置

静态设置 fontScale 属性为枚举类型中的其一

    <com.example.boldtext.TypefaceTextView
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:gravity="center"
        app:fontScale="bold"
        android:text="TypefaceTextView 加粗字体" />
动态设置
package com.example.boldtext

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val typefaceView = findViewById<TypefaceLTextView>(R.id.typeface_view)
        //设置加粗
        typefaceView.setTypefaceScale(TypefaceLTextView.TypefaceScale.MEDIUM)
    }
}

只能设置我们声明的枚举类型,如果项目需要扩展到更多粗度的话,可以自行增加!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1988011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SQL Server】端口安全配置:SQL Server的安全最佳实践与防火墙规则配置

目录 SQL Server 安全最佳实践 防火墙规则配置 示例&#xff1a;配置 Windows 防火墙规则 加密连接 示例代码&#xff1a;使用加密连接 安全注意事项 SQL Server 安全最佳实践 在进行任何网络或数据库系统的部署时&#xff0c;确保安全是至关重要的。SQL Server&#xf…

语法检测在线英语怎么做?5个检测技巧教会你

相信大家平时在撰写文章、报告或是任何形式的书面材料时&#xff0c;都会发现语法错误会很大程度地影响信息的传达和读者的理解。尤其是对于非母语的写作者来说&#xff0c;语法问题更是棘手。 但得益于语法检测在线免费工具的出现&#xff0c;现在可就再也不需要为语法错误而…

10款超好用的图纸加密软件推荐,2024企业常用图纸加密软件分享

在现代企业中&#xff0c;设计图纸和敏感数据的安全性至关重要。一旦图纸泄露&#xff0c;可能会对企业造成不可估量的损失。因此&#xff0c;选择一款高效、可靠的图纸加密软件显得尤为重要。 1. 安秉图纸加密软件 安秉图纸加密软件是一款专为保护工程图纸和设计文件安全的软…

【youcans动手学模型】YOLO5 (上)环境配置与测试

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【youcans动手学模型】YOLO5 &#xff08;上&#xff09;环境配置与测试 1. YOLO 简介2. YOLOv5 简介3. YOLOv5 下载4. 配置 PyCharm 环境5. 运行 YOLOv5 推理 1. YOLO 简介 YOLO (You Only Look On…

【溯源反制】反制攻击者-蚁剑低版本

目录 安装 攻击者获取防守方的权限 防守方反制攻击者 防守方获取攻击者的shell权限 安装 安装蚁剑2.0.7版本 链接&#xff1a;https://pan.baidu.com/s/1t40UxkZ2XuSWG6VCdGzvDw?pwd8888 提取码&#xff1a;8888 下载好后先打开Loader文件夹下的.exe文件&#xff0c;打…

2.如何定制 Dcat-admin list 中显示的信息

操作在xxxController.php文件中的 protected function grid() 中进行 定制显示的内容 protected function grid(){return Grid::make(new Robot(), function (Grid $grid) {// ->sortable() 新增一个排序的按钮在列标题中$grid->column(id)->sortable();// 正常字符…

STM32-OTA升级

一、OTA&#xff08;Over-The-Air&#xff09; OTA&#xff08;Over-The-Air&#xff09;是一种通过无线通信方式&#xff0c;为设备分发新软件、配置甚至更新加密密钥的技术。它允许中心位置向所有用户发送更新&#xff0c;确保每个接收者都无法拒绝、破坏或改变这些更新&…

C# Unity 面向对象补全计划 设计者模式 之 单例模式

本文仅作学习笔记与交流&#xff0c;不作任何商业用途&#xff0c;作者能力有限&#xff0c;如有不足还请斧正 本系列作为七大原则和设计模式的进阶知识&#xff0c;看不懂没关系 了解我的专栏C#面向对象与进阶:http://t.csdnimg.cn/mIitr&#xff0c;尤其是关于类的那篇文章即…

电脑屏幕录屏,5个技巧,精准捕捉!

电脑屏幕录屏已经成为了一种常见的行为&#xff0c;无论在工作还是生活中都发挥了重要作用。然而&#xff0c;对于许多人来说&#xff0c;如何进行电脑屏幕录屏可能仍然是一个谜团。 从选择合适的录屏软件到了解录制的技巧&#xff0c;都是需要探索和学习的内容。在这篇文章中…

数据库|SQLServer数据库:模糊查询的三种情况

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 就是字面意思&#xff0c;当数据库的查询条件并不是十分具体时就用到模糊查询&#xff0c;比如查询姓氏为雷的人名&#xff0c;就需要从姓名列模糊查询。 01 like关键字查询 当使用like关键字进行查询时&#xff0c;字…

国央企如何提高监管数据报送效率?

最新动向 近日&#xff0c;国家层面高度重视清理拖欠民营企业账款的问题&#xff0c;并出台了一系列相关政策&#xff0c;要求国有企业在偿还债务方面发挥示范作用。近期发布的报告强调了优化民营经济发展环境的重要性&#xff0c;并提出了六大重点工作&#xff0c;其中包括修…

50etf期权行权采用什么交割方式 ?

50ETF期权是欧式期&#xff0c;要到期日当天才能行权交制&#xff0c;其交割方式是实物交割买卖双方在到期行权日时需要准备一手交钱&#xff0c;一手收货或是一手交&#xff0c;一手收钱&#xff0c;如果持有期权到达到期日之前&#xff0c;投资者认为行权并不划算&#xff0c…

python.tkinter设计标记语言(语法2-语法解析器)

TOC 前言 本文只作为笔记记录。 TinText开源地址&#xff1a;https://github.com/Smart-Space/TinText 语法解析器 从前文可以看到&#xff0c;新的Tin标记语言非常简单&#xff0c;即便是加入嵌套关系&#xff0c;也只是标签级别做个标记就行了。&#xff08;在写这篇文章…

【Python机器学习】回归——局部加权线性回归

线性回归有一个问题就是有可能出现过拟合现象&#xff0c;因为它求的是具有最小均方误差的无偏估计。如果模型欠拟合将不能取得最好的预测效果。所以有些方法允许在估计中引入一些偏差&#xff0c;从而降低预测的均方误差。 其中一个方法就是局部加权线性回归&#xff08;LWLR…

学习记录——day27 进程间通信 IPC通信机制 消息队列 共享内存

目录 一、IPC通信机制 1、system V提供了三种IPC&#xff08;interprocess communication&#xff09;进程间通信方式 消息队列 共享内存 信号量集 2、该通信机制是独立于进程而存在的:当进程将数据写入该通信对象中后&#xff0c;即使进程已经结束&#xff0c;对象中保存的…

吴恩达机器学习COURSE1 WEEK2

COURSE1 WEEK2 多维特征 在线性回归中&#xff0c;往往特征不止一个&#xff0c;而是具有多维特征 例如&#xff0c;在预测房价的例子中&#xff0c;我们知道更多的信息&#xff1a; x 1 x_1 x1​&#xff1a;房屋的面积 x 2 x_2 x2​&#xff1a;卧室的数目 x 3 x_3 x3​&a…

【嵌入式】常用英文缩写及单词整理

目录 嵌入式常用英文缩写及单词整理1. 缩写部分2. 词汇部分3. 语句部分4. 调试部分5. 结束语相关文章&#xff1a; 嵌入式常用英文缩写及单词整理 1. 缩写部分 缩写全称翻译AADCAnalog-to-Digital Converter模/数转换器&#xff0c;模数转换器ADUApplication data unit应用数…

KBEngine ue5

前言 最近在试 KBEngine 的 ue4 项目&#xff0c;它在 ue4 下能够正常编译使用&#xff0c;但是现在都已经进入 ue5 时代&#xff0c;那么能不能将现有工程移到 ue5 下呢&#xff1f; 使用 ue5 打开工程的报错处理 1、DefaultBuildSettings BuildSettingsVersion.V5; kbeng…

python.tkinter设计标记语言(渲染2-渲染器)

TOC 前言 本文仅作为笔记记录。 在前文中&#xff0c;我们通过标记意义解释生成了带有明确渲染要求的参数组&#xff0c;以<title>为例&#xff0c;我们获取了title, level两个明确的渲染标记&#xff0c;这一部分由Tin标记解释器完成&#xff0c;不需要编写者花费过多…

亚马逊、eBay、沃尔玛等海外跨境电商测评自养号的技术解决方案

随着跨境电商的蓬勃发展&#xff0c;卖家们对于提升店铺流量、销量以及产品评价的需求日益迫切。在这一背景下&#xff0c;海外跨境电商测评成为了一个备受瞩目的领域。作为一家专注于此领域的技术型公司&#xff0c;凭借其深厚的技术积累和丰富的实战经验&#xff0c;为卖家们…