当前位置: 首页 > news >正文

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

在客户端中不论是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 属性用于设置字体粗度

  <TextViewandroid: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.boldtextimport android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSetclass MediumOldTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {private var mediumState: Boolean = falseinit {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.strokeWidthval style = paint.stylepaint.strokeWidth = 0.6fpaint.style = Paint.Style.FILL_AND_STROKEsuper.onDraw(canvas)paint.strokeWidth = strokeWidthpaint.style = style} else {super.onDraw(canvas)}}fun setMediumState(mediumState: Boolean) {this.mediumState = mediumStaterequestLayout()}}

优化后

去除一些无用逻辑、代码

package com.example.boldtextimport android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSetclass MediumTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {private var mediumState: Boolean = falseinit {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.6fpaint.style = Paint.Style.FILL_AND_STROKE}super.onDraw(canvas)}fun setMediumText(mediumText: Boolean) {this.mediumState = mediumTextrequestLayout()
//        postInvalidate()}}

使用方式

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

静态设置

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

动态设置

package com.example.boldtextimport android.support.v7.app.AppCompatActivity
import android.os.Bundleclass 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.boldtextimport android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSetopen class TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :AppCompatTextView(context, attrs, defStyleAttr) {private var mTypefaceScale: Float = 0.0fenum class TypefaceScale {MEDIUM, MEDIUM_SMALL, DEFAULT,}override fun onDraw(canvas: Canvas?) {if (mTypefaceScale == 0f) {return super.onDraw(canvas)}val strokeWidth = paint.strokeWidthval style = paint.stylepaint.strokeWidth = mTypefaceScalepaint.style = Paint.Style.FILL_AND_STROKEsuper.onDraw(canvas)paint.strokeWidth = strokeWidthpaint.style = style}fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) {mTypefaceScale = when (scale) {TypefaceScale.DEFAULT -> 0.0fTypefaceScale.MEDIUM_SMALL -> 0.6fTypefaceScale.MEDIUM -> 1.1f}postInvalidate()}}

使用方式

package com.example.boldtextimport android.support.v7.app.AppCompatActivity
import android.os.Bundleclass 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.TypefaceTextViewandroid:id="@+id/typeface_view"android:layout_width="match_parent"android:layout_height="45dp"android:gravity="center"android:text="TypefaceTextView 加粗字体" />

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

布局方式

   add(lParams(), typefaceTextView {gravity = gravityEndtypefaceScale = TypefaceScale.MEDIUM_SMALLtextSize = 14ftextColor = "#333333".toColorInt()})

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

import android.view.View
import android.view.ViewGroupinline 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 = gravityit.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() = noGetterset(value) {val scale = when (value) {
//            TypefaceScale.MEDIUM -> TypefaceTextView.TypefaceScale.MEDIUMTypefaceScale.MEDIUM_SMALL -> TypefaceTextView.TypefaceScale.MEDIUM_SMALLTypefaceScale.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.boldtextimport android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.support.v7.widget.AppCompatTextView
import android.util.AttributeSetclass TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :AppCompatTextView(context, attrs, defStyleAttr) {private var mTypefaceScale: Float = 0.0finit {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.6f2 -> 1.1felse -> 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.strokeWidthval style = paint.stylepaint.strokeWidth = mTypefaceScalepaint.style = Paint.Style.FILL_AND_STROKEsuper.onDraw(canvas)paint.strokeWidth = strokeWidthpaint.style = style}internal fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) {mTypefaceScale = when (scale) {TypefaceScale.DEFAULT -> 0.0fTypefaceScale.MEDIUM -> 0.6fTypefaceScale.BOLD -> 1.1f}invalidate()}}
静态设置

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

    <com.example.boldtext.TypefaceTextViewandroid:layout_width="match_parent"android:layout_height="45dp"android:gravity="center"app:fontScale="bold"android:text="TypefaceTextView 加粗字体" />
动态设置
package com.example.boldtextimport android.support.v7.app.AppCompatActivity
import android.os.Bundleclass 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)}
}

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

在这里插入图片描述

相关文章:

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

在客户端中不论是PC端&#xff0c;还是移动端主要价值之一就体现在用户交互方面&#xff0c;也就是用户体验了&#xff0c;接下来讲的是很常见的字体加粗问题 UI大找茬 深入浅出字体、字体库TextView文本渐变字体阴影、文字阴影字体加粗 - 定制化字体粗度 在开发中经常会遇到…...

ForkJoin框架的解析

Java 的 Fork/Join 框架是 Java 7 中引入的一种强大并发框架&#xff0c;旨在简化多线程编程&#xff0c;特别是对那些可以被递归地拆分成更小任务的任务。Fork/Join 框架的核心思想是将大任务拆分为多个小任务&#xff0c;并行运行这些小任务&#xff0c;然后将结果合并起来得…...

使用IDEA2019.1.4创建“hello world”java程序

使用IDEA创建“hello world”java程序分为4步&#xff1a; 创建工程->创建模块->创建库->创建类 1.创建工程 修改工程名称及地址 上步骤点击finish后&#xff0c;2019.1.4版本会自动弹出创建模块的窗口 2.创建模块 可以在上述窗口的基础上创建模块&#xff0c;也可…...

学习vue3 五,传送,缓存组件以及过渡和过渡列表

目录 Teleport传送组件 keep-alive缓存组件 transition动画组件 1. 过渡的类名 2. 自定义过渡class名 3. transition的生命周期 4.appear transition-group 1. 过渡列表 2. 列表的移动过渡 3. 状态过渡 Teleport传送组件 Teleport Vue 3.0新特性之一。 Teleport 是一…...

MyBatis快速学习

目录 前言 MyBatis的具体使用 一些小工具&#xff1a;MyBatisX 常见问题&#xff1a; 1.表中字段名和实体属性名不一致 2.按条件查询&#xff08;单条件&#xff09;时的&#xff0c;查询条件怎么编写 3.按条件查询&#xff08;多条件&#xff09; 4.多条件查询时&…...

24.8.3数据结构|双向循环链表、静态链表

双向循环链表 节点类型与双链表的节点类型完全相同双向循环链表的操作也与双链表的操作基本一致。 例题 将自然数一到N按由小到大的顺序沿顺时针方向围成一个圈&#xff0c;然后以一为起点先沿顺时针方向数到第N个数将其划去&#xff0c;再沿逆时针方向数到第K个数将其滑去&a…...

C语言典型例题28

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.5 输入一个华氏温度&#xff0c;要求输出摄氏温度。公式为C5/9(F-32)&#xff0c;要求输出要有文字说明&#xff0c;取两位小数 数学知识&#xff1a; &#xff08;1&#xff09;华氏温度与摄氏温度&#x…...

PHP企业培训考试系统小程序源码

&#x1f680;企业培训考试系统&#xff0c;赋能员工成长新引擎&#x1f4da; &#x1f331; 开篇&#xff1a;解锁企业培训新篇章 在快速变化的商业环境中&#xff0c;员工的能力提升是企业持续发展的关键。&#x1f680; 传统的培训方式已难以满足现代企业的需求&#xff0…...

进程状态(三)----- linux 中具体的进程状态(下)

目录 前言1. T && t 状态2. X 与 Z 状态3. 孤儿进程 前言 继上一篇文章 进程状态&#xff08;二&#xff09;----- linux 中具体的进程状态&#xff08;上&#xff09; 介绍了 linux 系统中具体的 R、S、D 状态&#xff0c;而这篇文章继续介绍 linux 系统中剩下的三种…...

关系型数据库(RDBMS,Relational Database Management System)

关系型数据库&#xff08;RDBMS&#xff0c;Relational Database Management System&#xff09;是一种结构化数据存储系统&#xff0c;它使用表&#xff08;Tables&#xff09;、行&#xff08;Rows&#xff09;和列&#xff08;Columns&#xff09;的结构来组织和管理数据。关…...

使用RK Docker环境编译RK SDK

文章目录 前言Docker介绍实验环境获取RK Docker镜像加载RK Docker镜像使用RK Docker环境编译SDK其它 前言 作为一名嵌入式Linux的学习者&#xff0c;目前编译各种平台&#xff0c;用的都是同一个编译机&#xff08;Ubuntu虚拟机&#xff09;。之前一直在折腾全志&#xff0c;所…...

免费【2024】springboot 付费自习室管理系统的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…...

【学习方法】高效学习因素 ② ( 学习动机 | 内在学习动机 | 外在学习动机 | 外在学习动机的调整方向 | 保护学习兴趣 | 高考竞争分析 )

文章目录 一、高效学习的其它因素 - 学习动机1、学习动机2、内在学习动机3、外在学习动机4、外在学习动机的问题所在5、外在学习动机的调整方向6、保护学习兴趣7、高考竞争分析 上一篇博客 【学习方法】高效学习因素 ① ( 开始学习 | 高效学习因素五大因素 | 高效学习公式 - 学…...

【学习笔记】A2X通信的协议(四)- A2X PC5通信(二)

目录 6.1.2.4 A2X PC5单播链接释放程序 6.1.2.4.1 概述 6.1.2.4.2 发起UE启动A2X PC5单播链接释放程序 6.1.2.4.3 目标UE接受的A2X PC5单播链接释放程序 6.1.2.4.4 发起UE完成的A2X PC5单播链接释放程序 6.1.2.4.5 异常情况 6.1.2.4.5.1 发起UE的异常情况 6.1.2.5 A2X …...

注意!!可能这是《网络管理员》旧教程最后一次考试,赶紧学起来

网络管理员是软考初级资格热门科目之一。近日在国家版本数据中心&#xff0c;小编查到网络管理员官方教程已经有2024最新版出来了&#xff0c;现在这一版教程说实话有些内容已经过时了&#xff0c;尤其新版教材也已经出现&#xff0c;小编推测明年大概率依据新版考试大纲出题&a…...

array postgre gsql 剔除

进行某种过滤或比较操作&#xff0c;判断不匹配的&#xff0c;数组 array 中列出的所有字符串 and a.Repunittree not like all (array[‘%0001003549950003%’,‘%000100460041%’,‘%000100460047%’,‘%000105880001%’ ,‘%000100020007%’,‘%000105830009%’,‘%0001058…...

【Matlab】零阶保持法:连续状态空间方程(含噪声,非线性)离散化处理方法

常用的离散化方法&#xff1a;零阶保持器&#xff08;zero-order hold&#xff0c;ZOH&#xff09;、欧拉法&#xff08;Euler&#xff09;、一阶保持器&#xff08;First-order hold&#xff0c;FOH&#xff09;。最常用的是前两种。 0.零阶保持器&#xff08;ZOH&#xff09…...

web自动化6-pytest⑦一些基本情况

命名规则 1)import pytest 测试文件名要以test_ 开头或 _test结尾 2&#xff09;类名需要以Test开头&#xff08;T&#xff09;&#xff0c;不能带有init方法 3&#xff09;函数名以test_开头&#xff08;t&#xff09; 符合规则框架才能找到用例&#xff0c;一条用例代表一条函…...

apache 漏洞

影响版本 Apache HTTP Server 2.4.49 某些Apache HTTPd 2.4.50也存在此漏洞 环境搭建 docker pull blueteamsteve/cve-2021-41773:no-cgid 漏洞复现 http://1.15.136.212:8080 1.使⽤poc curl http://1.15.136.212:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd...

简单的docker学习 第11章 镜像中心

第11章 镜像中心 Docker Hub 与阿里云都是 Docker 的公网镜像中心&#xff0c;用户可以将自己的镜像 push 到公网镜像中心中自己的镜像仓库&#xff0c;并可将仓库设置为私有库&#xff0c;使他人无法看到&#xff0c;更无法 pull&#xff0c;以保证镜像的安全性。不过&#x…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...