Android 字体大小(fontScale)不随系统设置变化

需求

App字体大小不变

如果用户将系统字体大小设置的非常大,可能导致APP的文字大小显示异常。

目标效果是,APP内字体大小不随系统设置的 字体大小 变化。

  • 原始效果

系统的字体大小设置为 超大 时:(字体大小 可变)

  • 目标效果

系统的字体大小设置为 超大 时:(字体大小 不变)

  •  系统设置中,字体大小设置为 超大 ,指的是如下图所示的设置


示例项目(Gitee开源)

Android/FontScale · 宋冠巡/示例 - 码云 - 开源中国 (gitee.com)

Android/FontScaleJava · 宋冠巡/示例 - 码云 - 开源中国 (gitee.com)

Android/FontScaleCompose · 宋冠巡/示例 - 码云 - 开源中国 (gitee.com)


解决方案

原理

在 Activity 初始化 Context 时,将 字体缩放比例(fontScale)始终设置为 1

实现方法

在基类 BaseActivity 中,重写 attachBaseContext() 方法,设置 Configuration.fontScale = 1f

说明

  1. attachBaseContext() 方法,在 onCreate() 方法之前调用,Activity获取构建页面所需的上下文配置时调用此方法。
  2. 在 attachBaseContext() 中,修改Configuration的参数,可以实现整个页面配置的修改;修改Configuration.fontScale,也就能实现字体大小的控制。
  3. 所有Activity均需要继承BaseActivity。因为将 fontScale 配置修改放置在了BaseActivity中,可以对APP的所有Activity页面生效。
  4. 当 android:configChanges="fontScale" 后,仍能够正常实现字体大小不变。

android:configChanges:指定Activity将自行处理的一个或多个配置更改。如果未指定,则如果系统中发生任何这些配置更改,将重新启动Activity 。

当 configChanges 设置为 fontScale 后,后台App重新进入前台时,Activity将不会重启,而是触发 onConfigurationChanged 后直接从后台进入前台。

注意

请注意,本方法不适用于 Compose 项目。

Compose项目字体大小不变的办法,请参考后面的《Compose实现》章节。


核心代码

Kotlin 代码

    override fun attachBaseContext(newBase: Context?) {super.attachBaseContext(newBase)overrideFontScale(newBase)}/*** 重置配置 fontScale:保持字体比例不变,始终为 1.*/private fun overrideFontScale(context: Context?) {if (context == null) returncontext.resources.configuration.let {it.fontScale = 1f // 保持字体比例不变,始终为 1.applyOverrideConfiguration(it) // 应用新的配置}}

applyOverrideConfiguration()方法只能被调用一次,且必须在 getResources() 和 getAssets() 前调用。

BaseActivity-Kotlin 完整代码

package com.example.fontscaleimport android.content.Context
import androidx.appcompat.app.AppCompatActivity/***  所有Activity的基类*/
open class BaseActivity : AppCompatActivity() {override fun attachBaseContext(newBase: Context?) {super.attachBaseContext(newBase)overrideFontScale(newBase)}/*** 重置配置 fontScale:保持字体比例不变,始终为 1.*/private fun overrideFontScale(context: Context?) {if (context == null) returncontext.resources.configuration.let {it.fontScale = 1f // 保持字体比例不变,始终为 1.applyOverrideConfiguration(it) // 应用新的配置}}}

Java 代码

    @Overrideprotected void attachBaseContext(Context newBase) {super.attachBaseContext(newBase);overrideFontScale(newBase);}/*** 重置配置 fontScale:保持字体比例不变,始终为 1.*/private void overrideFontScale(Context context) {if (context == null) return;Configuration configuration = context.getResources().getConfiguration();configuration.fontScale = 1f;applyOverrideConfiguration(configuration);}

BaseActivity-Java 完整代码

package com.example.fontscalejava;import android.content.Context;
import android.content.res.Configuration;import androidx.appcompat.app.AppCompatActivity;/*** 所有Activity的基类*/
public class BaseActivity extends AppCompatActivity {@Overrideprotected void attachBaseContext(Context newBase) {super.attachBaseContext(newBase);overrideFontScale(newBase);}/*** 重置配置 fontScale:保持字体比例不变,始终为 1.*/private void overrideFontScale(Context context) {if (context == null) return;Configuration configuration = context.getResources().getConfiguration();configuration.fontScale = 1f;applyOverrideConfiguration(configuration);}}


Compose实现

Compose项目,经过测试,在 attachBaseContext 中,applyOverrideConfiguration 无效;

并且,如果设置了 android:configChanges,也需要在 onConfigurationChanged 重新配置 fontScale。否则,字体大小配置修改后,当后台App重新进入前台时,Activity将不会重启,而是直接从后台进入前台,页面字体将直接变成 超大

解决方案

attachBaseContext onConfigurationChanged 中,设置 getResource().getConfiguration().fontScale 的值始终为 1.

核心代码

    override fun attachBaseContext(newBase: Context?) {super.attachBaseContext(newBase)setFontScale()}override fun onConfigurationChanged(newConfig: Configuration) {super.onConfigurationChanged(newConfig)// 如果 Activity 配置了 android:configChanges 属性,则对应的系统设置修改后,将进入此函数,不再重启 ActivitysetFontScale()}/*** 保持字体比例不变,始终为 1.*/private fun setFontScale() {resources.configuration.fontScale = 1f}

BaseActivity-Compose 完整代码

package com.example.fontscalecomposeimport android.content.Context
import android.content.res.Configuration
import androidx.activity.ComponentActivity/***  所有Activity的基类*/
open class BaseActivity : ComponentActivity() {override fun attachBaseContext(newBase: Context?) {super.attachBaseContext(newBase)setFontScale()}override fun onConfigurationChanged(newConfig: Configuration) {super.onConfigurationChanged(newConfig)// 如果 Activity 配置了 android:configChanges 属性,则对应的系统设置修改后,将进入此函数,不再重启 ActivitysetFontScale()}/*** 保持字体比例不变,始终为 1.*/private fun setFontScale() {resources.configuration.fontScale = 1f}}

configChanges 配置方法

android:configChanges 配置方法,参考如下博客

Activity生命周期_宋冠巡的博客-CSDN博客

在这里插入图片描述


不推荐方法一:重写getResources()

原因

在Activity中重写 getResources(),此方法是不符合逻辑的,且可能造成性能问题。

getResources() 方法,会在页面获取资源时多次调用,而不是在页面初始化时调用一次。所以,在此处修改配置是不符合逻辑的。

另外,如果页面布局比较复杂,调用 getResources() 的次数就会非常多,在getResources()方法内耗费时间更新Configuration,可能会 造成卡顿 

不推荐代码示例

    @Overridepublic Resources getResources() {Resources resources = super.getResources();Configuration configuration = resources.getConfiguration();// 设置字体大小不随系统设置变化。字体大小(字体比例)始终设置为默认值if (configuration.fontScale != 1) { // 字体大小(字体比例)为非默认值configuration.fontScale = 1; // 字体大小(字体比例)设置为默认值resources.updateConfiguration(configuration, resources.getDisplayMetrics());}return resources;}

getResources()调用日志

  • 进入页面时,getResources() 方法调用的日志

Resources.updateConfiguration() 已废弃

此方法已废弃,不应再使用。


不推荐方法二:sp 换成 dp

将布局文件中 android:textSize 属性的字号单位 sp 换成 dp。这种方式是 错误的 

原因

  1. 将 sp 改为 dp,需要将所有用到 textSize 属性的控件全部进行修改,基本意味着项目中的所有布局文件都要修改,这明显不合理。
  2. sp 是Android推荐的字号单位,在 textSize 中使用其他类型的单位,Android Studio 是有 Warning 警告的。

Warning 警告示例

尺寸 官方说明

尺寸的官方文档


参考

Configuration 官方说明

Configuration  |  Android Developers (google.cn)

attachBaseContext 官方说明

Activity  |  Android Developers (google.cn)

applyOverrideConfiguration 官方说明

ContextThemeWrapper  |  Android Developers (google.cn)

createConfigurationContext 官方说明

Context  |  Android Developers (google.cn)

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

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

相关文章

Android 自带的字体库、字体样式

1、设置字体 android:fontFamily“字体样式” 1、sans-serif-smallcaps (左边只设置字体,右边设置加粗) 2、sans-serif 3、cursive 4、sans-serif-black 5、sans-serif-condensed-light 6、sans-serif-thin 7、serif 8、serif-monospa…

android屏幕大小字体大小,Android字体大小自适应不同分辨率的解决办法

Android字体大小自适应不同分辨率的解决办法 今天有人问我,Android系统不同分辨率,不同大小的手机,字体大小怎么去适应呢?其实字体的适应和图片的适应是一个道理的。 一、原理如下: 假设需要适应320x240,48…

Android切换字体

有时候需要根据UI需求切换项目字体&#xff0c;步骤如下&#xff1a; 准备字体文件&#xff0c;示例使用ttf文件&#xff0c;新建font文件夹&#xff1a; 将ttf文件放到res/font目录下 设置全局字体&#xff0c;系统主题添加 <item name"android:fontFamily">f…

Android 字体颜色设置及颜色表

1、在android中经常看到设置的颜色为八位的十六进制的颜色值&#xff0c;例如&#xff1a; public static final class color { public static final int lightblue0x7f040000; } 或者在Java中tx.setTextColor(0xffff00f); 说明&#xff1a; 0xffff00ff是int类型的数据&#…

IOS字体与安卓字体渲染不一致

IOS字体与安卓字体渲染不一致 问题: 前端开发中经常会遇到各种各样的兼容问题,记录一次IOS字体与安卓字体渲染不一致,当字体包名字中包含’-Bold’时 错误代码如下: font-family: DINAlternate-Bold ; font-weight: bold;IOS: 不会渲染’font-weight: bold’只是加载了’…

android中文字体加粗,android TextView设置中文字体加粗实现方法

android TextView设置中文字体加粗实现方法 英文设置加粗可以在xml里面设置: 复制代码 代码如下: android:textStyle="bold" 英文还可以直接在String文件里面直接这样填写: 复制代码 代码如下: Plain, bold, italic, bold-italic b代码加粗,i代表倾斜 中文设置加粗就…

android常用字体代码,Android TextView设置字体风格多种组合

在开发应用过程中经常会遇到显示一些不同的字体风格的信息犹如默认的LockScreen上面的时间和充电信息。对于类似的情况,可能第一反应就是用不同的多个TextView来实现,对于每个TextView设置不同的字体风格以满足需求。 这里推荐的做法是使用Android.text.*;和android.text.sty…

Android 字体粗细的设置

转载:https://juejin.im/post/597d88f75188257fc2177c36 如何实现 “中间这几个字要加粗&#xff0c;但是不要太粗&#xff0c;比较纤细的那种粗” &#xff1f; 分享一个最近做业务遇到的简单又蛮有意思的的文本显示处理过程。具体就是有这么一段文字&#xff0c;类似“转盘…

Android字体引入

2个方案&#xff1a;①xml引入、②java代码引入。 效果图&#xff1a; 方法①&#xff1a;xml引入&#xff1a; 1.创建font目录&#xff1a; 2.把字体库复制到font目录下&#xff1a; 3.xml中&#xff0c;使用fontFamily引入字体库&#xff1a; <TextViewandroid:text"…

Android字体样式修改

效果图 准备字体 Download Alibaba Sans比如阿里巴巴普惠体&#xff0c;也可以其他网站找一些对应的资源。 字体使用 将字体文件放到res/font文件夹下&#xff0c;如果没有font文件&#xff0c;则新建一个。 添加到font路径下的字体文件&#xff0c;明明不能是汉字&#xff…

玩转安卓字体

起因 最近公司有个需求&#xff0c;需要做 Widget &#xff0c;内心其实是拒绝的&#xff0c;因为这个玩意儿特别难用&#xff0c;而且限制重重&#xff0c;但没办法&#xff0c;也不能不做&#xff0c;那就开始吧。 本来以为挺简单的东西&#xff0c;一个列表展示数据&#…

iPadPro看电影之MKV转MP4视频格式教程

拥有了苹果iPadPro如果不看高清电影那就有点可惜了&#xff0c;虽说在线看电影也不错&#xff0c;但就目前这种网络环境&#xff0c;还别说很多时候没有Wifi网络&#xff0c;即使能上网很多时候网速也无法支持流畅的在线播放普清电影&#xff0c;更不用说高清电影了。怎么办&am…

如何向ipad上传视频(使用iTunes)

1.先对iTunes做个简单介绍&#xff1a; iTunes是一款媒体播放器的应用程序&#xff0c;2001年1月10日由苹果电脑在旧金山的Macworld Expo推出&#xff0c;用来播放以及管理数字音乐和与视频文件。iTunes能连接到iTunes Store&#xff0c;以便下载购买的数字音乐、音乐影片、电视…

Mac电脑使用:通过Mac电脑导出iPhone手机里面的视频(不是iTunes导出视频的方法)

分享一个通过Mac电脑导出iPhone手机里面的视频的方法,这个方法和通过iTunes导出手机视频的方法是并行关系。 方法很简单,就是通过Mac电脑系统里面自带的图像捕捉工具来操作。 具体步骤如下所示: 1.把iPhone手机连接到你的Mac电脑上面,然后打开Launchpad; 2.在Launchpad中找…

苹果手机iphone如何播放电脑中的视频

用手机看视频已经是人们习以为常的事情了&#xff0c;随着手机容量的增大&#xff0c;很多人选择把视频下载到手机本地观看&#xff0c;但是有些视频我们存放在电脑上&#xff0c;想用手机看怎么办呢&#xff1f;很多人选择把视频用数据线传输到手机上&#xff0c;但是这样略显…

如何在IPad上优雅地看移动硬盘中的视频

这里用到的是SMB协议&#xff0c;Win10自带 文章目录 如何开启SMB如何共享文件如何在IPad上访问共享文件如何在IPad上看视频呢&#xff1f; 如何开启SMB 众所周知&#xff0c;windows的SMB默认是关闭的&#xff0c;下文首先介绍如何开启首先&#xff0c;进入控制面板-程序&…

ipad 共享 计算机,ipad与电脑怎么共享视频

有了Ipad以后&#xff0c;天天就想着怎么玩Ipad&#xff0c;那么大家知道ipad与电脑怎么共享视频吗?下面学习啦小编就为大家带来了ipad与电脑共享视频实现在iPad上看电脑里的电影的方法。 ipad与电脑共享视频方法 1.首先需要在电脑上先打开 “家庭共享”功能。 在PC上选择 文件…

平板可以看html文档吗,iPad如何看电脑里的视频 如何使用Ipad看电脑里的电影

电脑上的视频怎么在iPad上观看&#xff1f; 如何在ipad播放电脑中的视频 首先&#xff0c;看你的视频格式。如果是mp4&#xff0c;就可以直接放入ipad自带浏览器或者通过itunes直接传。其他格式的需要下载第三方播放器&#xff0c;目前使用较多的支持高清播放的有Oplayer&#…

windows10 共享视频到 Ipad

windows10 共享视频到 Ipad(iphone) 写作初衷前期准备教程开始共享文件夹设置控制面板设置Windows Media Player 设置共享内容图片分享 后来的话 写作初衷 受限于Ipad系统的封闭性&#xff0c;向其传输数据需要下载超级难用的Itunes&#xff0c;使用过程非常糟心。而使用Ipad下…

如何通过电脑向ipad传电影视频(不用越狱)

前言 为了能在ipad上看电脑上已下载的电影&#xff0c;我可是试了各种方法&#xff0c;心好累&#xff0c;还好终于解决了。不得不说&#xff0c;网上没一个靠谱的答案&#xff01; 方法一 如果电影本身的格式是 mp4&#xff0c;mov&#xff0c;m4a格式&#xff0c;通过官方的i…