學徒淺析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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章