Android系统的文字设置变更会影响到应用页面的展示,一般的APP都是禁止跟随系统文字设置进行变化的。那么针对系统文字适配的过程中,
1、针对系统字体变更的应对方法:
(1)可以通过在AndroidMainfest.xml中配置configChange="fontScale"规避Activity生命周期的重启,当系统设置发生变更时,会引起当前应用的重启,声明周期变更为onDestroy()->onCreate()->onRestoreInstanceState()->onResume();如果设置了fontScale,声明周期变更为onRestart()->onResume()。
(2)设置字体单位为DIP/DP,可以避免页面字体跟随系统字体设置发生变化。虽然Android建议使用SP为单位,但是在效果面前,我们还是跟着需求走吧。具体原因在2中讲述。
添加fontscale时
06-20 11:16:35.139 23009-23009/com.example.demo_1 I/zheng.li: onCreate()
06-20 11:16:35.159 23009-23009/com.example.demo_1 I/zheng.li: onResume()
按HOMO键,进入后台,切换系统文字大小
06-20 11:16:41.062 23009-23009/com.example.demo_1 I/zheng.li: onPause()
06-20 11:16:41.259 23009-23009/com.example.demo_1 I/zheng.li: onSaveInstanceState()
06-20 11:16:41.260 23009-23009/com.example.demo_1 I/zheng.li: onStop()
重新打开应用页面
06-20 11:16:50.714 23009-23009/com.example.demo_1 I/zheng.li: onRestart()
06-20 11:16:50.717 23009-23009/com.example.demo_1 I/zheng.li: onResume()
未添加fontscale时
06-20 11:17:11.192 23655-23655/com.example.demo_1 I/zheng.li: onCreate()
06-20 11:17:11.213 23655-23655/com.example.demo_1 I/zheng.li: onResume()
按HOMO键,进入后台,切换系统文字大小
06-20 11:17:13.913 23655-23655/com.example.demo_1 I/zheng.li: onPause()
06-20 11:17:14.107 23655-23655/com.example.demo_1 I/zheng.li: onSaveInstanceState()
06-20 11:17:14.109 23655-23655/com.example.demo_1 I/zheng.li: onStop()
重新打开应用页面
06-20 11:17:26.871 23655-23655/com.example.demo_1 I/zheng.li: onDestroy()
06-20 11:17:27.140 23655-23655/com.example.demo_1 I/zheng.li: onCreate()
06-20 11:17:27.149 23655-23655/com.example.demo_1 I/zheng.li: onRestoreInstanceState()
06-20 11:17:27.163 23655-23655/com.example.demo_1 I/zheng.li: onResume()
2、setTextSize()的使用
setTextSize有两种入参形式,分别如下:
(1)setTextSize(float size)不指定数值类型,默认为SP,即实质执行的是setTextSize(TypedValue.COMPLEX_UNIT_SP, float size)。 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;
}
在该方法中,dip/dp在转换成px时,是直接value * metrics.density,而sp在转换成px时,是直接value * metrics.scaledDensity。在1中提到使用dp可以避免跟随系统字体设置发生变化。原因就在于scaledDensity会根据用户在运行时对字体大小的设置以小增量的形式进行调整。而density是固定值。
3、getDimenison()的使用
getDimenison()是用来获得在dimen.xml中配置的数据,该方法的返回值是换算后的PX值,实质执行的依然是TypedValue.applyDimension(unit, size, r.getDisplayMetrics())。
public float getDimension(@DimenRes int id) throws NotFoundException {
final TypedValue value = obtainTempTypedValue();
try {
final ResourcesImpl impl = mResourcesImpl;
impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
} finally {
releaseTempTypedValue(value);
}
}
因此,如果要把getDimenison作为入参调用setTextSize(),必须声明数值类型为TypedValue.COMPLEX_UNIT_PX,否则setTextSize会把入参看成是SP类型的数据导致再一次执行PX转换操作,最终影响到实际效果的展示。
当把.9.png设置为背景图片后(android:background),一旦density发生变更,.9.png图片会因密度变化出现拉伸等现象,即宽高出现了等比例的缩放,原因在于设置.9.png时宽高设置的都是自适应wrap_content。此时适配的方法是在布局中指定初始宽高和maxHeight/maxWidth,或在代码中动态设置setWidth/setHeight。需要注意的是,在调用setWidth/setHeight时,当设置的宽高比当前宽高小时,该方法是不起作用的,此时需要通过getLayoutParams().width/getLayoutParams().height进行设置。
注:density的变更更多的是由表示设置引起的,同样可以使用命令: adb shell wm density XXX,将手机调成特定的density