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