学徒浅析Android——系统文字大小的适配

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)。
   (2)setTextSize(int unit, float size)指定数值类型。
   setTextSize实质调用的是TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),即将数值统一转换成PX单位。
  
 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转换操作,最终影响到实际效果的展示。
   
4、density变更对.9.png的影响

     当把.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



你可能感兴趣的:(Android开发)