android改变整个app字体大小,Android APP字体随系统字体调整造成界面布局混乱问题解决方案...
一、遇到的问题:
当用户调整系统字体大小的时候,APP的字体一般也都会跟随改变,进而导致某些界面布局排版混乱。
下面先说一下关于sp单位的理解
sp单位除了受屏幕密度影响外,还受到用户的字体大小影响,通常情况下,建议使用sp来跟随用户字体大小设置。除非一些特殊的情况,不想跟随系统字体变化的,可以使用dp”。按照这么说,布局宽高固定写死的地方应该统一用dp显示字体,因为一旦用户在设置中调大字体,宽高为固定值的布局显示就乱了。
二、 解决方案:
1. 强制实现所有界面都的字体都不随系统字体大小而改变,在工程的BaseActivity中添加下面的代码。利用Android的Configuration类中的fontScale属性,其默认值为1,会随系统调节字体大小而发生变化,如果我们强制让其等于默认值,就可以实现字体不随调节改变,
@Override
public Resources getResources() {
Resources resources = super.getResources();
if (resources != null) {
Configuration configuration = resources.getConfiguration();
if (configuration != null && configuration.fontScale != 1.0f) {
configuration.fontScale = 1.0f;//这里只设置字体,故不使用下面注释的方法
// configuration.setToDefaults();
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}
}
return resources;
}
注意: Android 8.0后在Application中复写上述方法是无效的 (原因暂不清楚,有知道的大佬欢迎指出)。此外,在任意一个Activity中如上覆盖了getResources方法后,会让其它Activity的字体也变的独立于系统配置(这里的Activity只针对重新create的,如当前 Activity 的 fragment,因为没有重新onCreate,就不会重绘进而改变字体)。我的理解是,新的 Activity 会载入上面更新后的 Configuration,而现有的 Activity 则不会更新。所以此方式我只建议用在BaseActivity中实现全部界面字体不随系统更改。
2. 在具体的界面把不想要放大的View字体单位设置为dp
三、原理解析:
到底为什么设置为sp,会导致字体随系统字体大小而改变?
从文字设定大小的入口看,TextView.setTextSize(float size)方法来看:
/**
* Set the default text size to the given value, interpreted as "scaled
* pixel" units. This size is adjusted based on the current density and
* user font size preference.
*
*
Note: if this TextView has the auto-size feature enabled than this function is no-op.
*
* @param size The scaled pixel size.
*
* @attr ref android.R.styleable#TextView_textSize
*/
@android.view.RemotableViewMethod
public void setTextSize(float size) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
/**
* Set the default text size to a given unit and value. See {@link
* TypedValue} for the possible dimension units.
*
*
Note: if this TextView has the auto-size feature enabled than this function is no-op.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
*
* @attr ref android.R.styleable#TextView_textSize
*/
public void setTextSize(int unit, float size) {
if (!isAutoSizeEnabled()) {
setTextSizeInternal(unit, size, true /* shouldRequestLayout */);
}
}
private void setTextSizeInternal(int unit, float size, boolean shouldRequestLayout) {
Context c = getContext();
Resources r;
if (c == null) {
r = Resources.getSystem();
} else {
r = c.getResources();
}
setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),
shouldRequestLayout);
}
@UnsupportedAppUsage
private void setRawTextSize(float size, boolean shouldRequestLayout) {
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(size);
if (shouldRequestLayout && mLayout != null) {
// Do not auto-size right after setting the text size.
mNeedsAutoSizeText = false;
nullLayouts();
requestLayout();
invalidate();
}
}
}
可以看到,如果没有设置字体单位的时候,默认会分配 TypedValue.COMPLEX_UNIT_SP ,即 sp 单位,而最终的值会通过TypedValue.applyDimension(unit, size, r.getDisplayMetrics()) 方法计算出来赋值给 setRawTextSize 方法,所以接下来看怎么计算的:
/**
* Converts an unpacked complex data value holding a dimension to its final floating
* point value. The two parameters unit and value
* are as in {@link #TYPE_DIMENSION}.
*
* @param unit The unit to convert from.
* @param value The value to apply the unit to.
* @param metrics Current display metrics to use in the conversion --
* supplies display density and scaling information.
*
* @return The complex floating point value multiplied by the appropriate
* metrics depending on its unit.
*/
public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}
可以看到,当单位为 COMPLEX_UNIT_SP时,取值为 value * metrics.scaleDensity;所以接下来看 metrics.scaleDensity 的取值:
/**
* A scaling factor for fonts displayed on the display. This is the same
* as {@link #density}, except that it may be adjusted in smaller
* increments at runtime based on a user preference for the font size.
*/
public float scaledDensity;
public void setTo(DisplayMetrics o) {
if (this == o) {
return;
}
widthPixels = o.widthPixels;
heightPixels = o.heightPixels;
density = o.density;
densityDpi = o.densityDpi;
scaledDensity = o.scaledDensity;
xdpi = o.xdpi;
ydpi = o.ydpi;
noncompatWidthPixels = o.noncompatWidthPixels;
noncompatHeightPixels = o.noncompatHeightPixels;
noncompatDensity = o.noncompatDensity;
noncompatDensityDpi = o.noncompatDensityDpi;
noncompatScaledDensity = o.noncompatScaledDensity;
noncompatXdpi = o.noncompatXdpi;
noncompatYdpi = o.noncompatYdpi;
}
public void setToDefaults() {
widthPixels = 0;
heightPixels = 0;
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
densityDpi = DENSITY_DEVICE;
scaledDensity = density;
xdpi = DENSITY_DEVICE;
ydpi = DENSITY_DEVICE;
noncompatWidthPixels = widthPixels;
noncompatHeightPixels = heightPixels;
noncompatDensity = density;
noncompatDensityDpi = densityDpi;
noncompatScaledDensity = scaledDensity;
noncompatXdpi = xdpi;
noncompatYdpi = ydpi;
}
注释说明了,scaleDensity 不仅仅受设备的 density 影响,还受用户设定的字体尺寸影响。DisplayMetrics.scaleDensity 在 DisplayMetrics 类中,并没有初始化的地方,可它是一个 public 的字段,也就是说可以被外部赋值初始化。真正为 DisplayMetrics 中各个字段赋值的地方,在 ResourcesImpl 中,有一个 updateConfiguration() 方法,在其中,就有对 scaleDensity 进行初始化的逻辑。
public void updateConfiguration(Configuration config, DisplayMetrics metrics,
CompatibilityInfo compat) {
//省略部分代码
//...........
if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
mMetrics.densityDpi = mConfiguration.densityDpi;
mMetrics.density =
mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
}
// Protect against an unset fontScale.
mMetrics.scaledDensity = mMetrics.density *
(mConfiguration.fontScale != 0 ? mConfiguration.fontScale : 1.0f);
//省略部分代码
//...........
}
可以看到,这里又引入了一个新的计算因子,fontScale。而从 Configuration 的源码又了解到,fontScale 默认值为 1 ,这也就是为什么通常情况下,density 和 scaleDensity 的值是相等的,它们分别影响了 dp 和 sp 最终渲染出来的像素尺寸。
所以,我们要控制字体不随系统字体改变的本质,就是通过修改 fontScale 的值为1,这也就是我们方法1这么做的原因。
好文分享:当你在设置里修改字体大小的时候,到底在修改什么
Android View篇之 字体大小 调整滑杆的实现
Android 仿微信/支付宝 字体大小 调整控件
来源:oschina
链接:https://my.oschina.net/u/4398725/blog/4547034
android改变整个app字体大小,Android APP字体随系统字体调整造成界面布局混乱问题解决方案...相关推荐
- Android APP字体随系统字体调整造成界面布局混乱问题解决方案
一.遇到的问题 当用户调整系统字体大小的时候,APP的字体一般也都会跟随改变,进而导致某些界面布局排版混乱. 下面先说一下关于sp单位的理解 sp单位除了受屏幕密度影响外,还受到用户的字体大小影响,通 ...
- android 7.1 字体更换,Android APP字体随系统字体调整造成界面布局混乱问题解决方案...
一.遇到的问题: 当用户调整系统字体大小的时候,APP的字体一般也都会跟随改变,进而导致某些界面布局排版混乱. 下面先说一下关于sp单位的理解 sp单位除了受屏幕密度影响外,还受到用户的字体大小影响, ...
- Android App修改字体大小,且不随系统字体大小更改
在做混合开发时发现,无论是APP内的字体大小,还是前端的字体大小,都会随着系统字体大小发生变化.当遇到老人字体(特大号字体)时,有些页面的布局就乱掉了.而玩过游戏的都知道,所有游戏APP的字体都不会随 ...
- Android全局修改字体大小,Android 仿微信全局字体大小调整
image 目录 一.前言 二.效果预览 三.实现步骤 1.自定义字体调整控件 2.滑动按钮改变当前页面预览字体大小 3.返回时,保存放大倍数并重启应用 4.初始化应用时配置字体放大倍数. 四.Dem ...
- R语言ggplot2可视化改变字体大小实战:单个图片设置字体大小、全局设置字体大小
R语言ggplot2可视化改变字体大小实战:单个图片设置字体大小.全局设置字体大小 目录
- 修改ToolBar的标题、子标题字体大小和颜色,toolbar menu字体的大小和颜色以及注意事项
在 Android 5.0 开始推出一个 Material Design 风格的导航Toolbar 控件.由于Toolbar的可定制度高,所以已经逐步替代掉了ActionBar.可以自定义以下几种元素 ...
- html代码字号div style=,div字体大小设置 css设置div中字体大小尺寸样式
div字体大小设置 css设置div中字体大小尺寸样式设置篇 在css div布局中常常对div字体大小设置,这篇ThinkCSS为大家介绍div中字体大小尺寸样式设置,通过直接在div标签加字体大小 ...
- div怎么在css中设置字体大小,div字体大小设置 css设置div中字体大小尺寸样式
div字体大小设置 css设置div中字体大小尺寸样式设置篇 在css div布局中常常对div字体大小设置,这篇ThinkCSS为大家介绍div中字体大小尺寸样式设置,通过直接在div标签加字体大小 ...
- android改变整个app字体大小,Android系统字体大小如何影响app的字体大小?
在Android应用开发过程中,一定会碰到本来完美的布局,在系统字体大小设置[最大]时变成一团浆糊.解决办法网上也有很多,但是分析原理的却几乎没看到.博主在碰到问题的第一时间也是直接用了网上的方法,即 ...
最新文章
- PAT甲级1108 Finding Average :[C++题解]stof、字符串变成浮点数、try和catch捕获异常、C++语法题
- python_day10_并发编程
- SAP 3D visual enterprise viewer 9.0 的下载方式
- java json 易用_Java中 Json的使用
- leetcode 115. 不同的子序列(dp)
- 有了 IP 地址,为什么还要用 MAC 地址?
- 【BZOJ3566】概率充电器,树形概率DP
- “评论王争夺赛”活动,第4期开始啦!
- Qt实现判断鼠标左右键信号
- HTML跳转php没反应的问题解决
- 【LeetCode】马三来刷题之Valid Anagram
- 基于wincap写抓包程序
- python 爬虫 爬取 小米有品 全网 商品数据
- Mikrotik RouterOS路由器和华为交换机链路聚合+VRRP+单线多拨
- 朋友圈利诱裂变遭封杀,私域流量成裂变新关键
- IIS 服务器的安装和配置
- android手机更改手机密码,手机忘记密码如可解决 安卓手机重置密码教程【详解】...
- 【稻韵果香,以梦为家】云和恩墨大讲堂电子期刊第九期
- tomat startup.bat 日志乱码问题解决
- 超详细IntelliJ IDEA安装教程
热门文章
- python iterable对象_Python迭代器Iterable判断方法解析
- R语言,中文排序问题
- 数据结构c语言版期末考试试题及答案,数据结构c语言版试题大全(含答案)
- 中学德育工作汇报材料
- 微软投屏器 android,微软 Your Phone 新功能:可同时投屏多款 Android 应用
- 成都市武侯计算机实验小学官网,成都市武侯计算机实验小学:挖掘英语教材 聚焦核心素养...
- 大学计算机课代表竞选稿,竞选大学课代表演讲稿
- JAVA JDK1.8 时间戳与时间格式化 实用工具类
- 测试矩阵是什么,小孩子都懂的,你该不会不知道吧
- 热点 | 天猫精灵卖出100万台,中国智能音箱市场将井喷?