前言: 最近公司做了橫屏手持車載設備,屏幕和通常的手機屏幕差別不大,我們是按照1334*750的設計圖尺寸做的,橫屏適配和豎屏適配方式是不一樣的,橫屏的像素寬,橫向佈局不會太複雜,通常"match_parent"或權重就可以滿足橫向設計要求,但是高度就不一樣了,比如設計圖的高度是750px,幾乎只有橫向像素的一半,如果豎屏內容需要滑動顯示倒無所謂了,對於車載端,主要界面偏偏都不是大篇幅的需要高度滑動展示,通常是一個屏幕剛好展示完,所以我們會藉助適配框架AutoSize來按照屏幕高度來適配佈局,後面新加了一個需求需要全局改變字體大小,通過百度扒拉扒拉,97%的人都說重寫getResources得到resources的configuration,將configuration.fontscale值改變,嘿嘿,這簡單吧!如果這樣想就錯了,嗚嗚,容我細細道來:
遇見的卡殼問題: autosize的佈局適配原理也是對DisplayMetrics做相應修改,而字體大小縮放也是更新DisplayMetrics,所以,如果你重寫getResources更新fontscale,那麼autosize的適配必將失效,後來想既然先設置autosize後更新fontscale適配失效,那順序反過來會怎樣?反過來會怎樣呢?先更新fontscale後設置autosize適配會讓適配生效字體縮放失效,好了,說了半天那我們來說替代方案吧:
第一步:現在設計給了三種標準字體大小:16、18、23, 大致思路是定義字體大小屬性,在attrs中定義不同字體大小屬性值,現在以兩種字體爲例:
<!--字體大小屬性-->
<attr name="text_size_15sp" format="reference|dimension"/>
<attr name="text_size_17sp" format="reference|dimension"/>
第二步:定義與三種字體對應的主題如
<style name="DayStandardTheme" parent="DayTheme">
<item name="text_size_15sp">@dimen/standard_text_15</item>
<item name="text_size_17sp">@dimen/standard_text_17</item>
</style>
<!--白天大字體-->
<style name="DayMiddleTheme" parent="DayTheme">
<item name="text_size_15sp">@dimen/middle_text_15</item>
<item name="text_size_17sp">@dimen/middle_text_17</item>
</style>
<!--白天超大字體-->
<style name="DayLargeTheme" parent="DayTheme">
<item name="text_size_15sp">@dimen/large_text_15</item>
<item name="text_size_17sp">@dimen/large_text_17</item>
</style>
第三步:佈局文件的字體樣式設置字體大小,這裏強烈建議將TextView的字體樣式提出來,比如我常常會這樣寫:
<style name="text_style_17dp_white">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">?attr/text_size_17sp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
注意: 寫"textSize"時使用主題屬性引用: ?attr/text_size_17sp
第四步:BaseActivity裏動態設置主題
//字體大小級別,1:"標準" 2:"中" 3:"大"
int fontState=2;
if(DayNightHelper.isDay()){
//設置白天主題,同時考慮字體大小狀態
if(fontState==1){
//設置標準字體大小
setTheme(R.style.DayStandardTheme);
}else if(fontState==2){
//設置中號字體大小
setTheme(R.style.DayMiddleTheme);
}else if(fontState==3){
//設置大號字體大小
setTheme(R.style.DayLargeTheme);
}
}else{
//設置夜晚主題,同時考慮字體大小狀態
if(fontState==1){
//設置標準字體大小
setTheme(R.style.NightStandardTheme);
}else if(fontState==2){
//設置中號字體大小
setTheme(R.style.NightMiddleTheme);
}else if(fontState==3){
//設置大號字體大小
setTheme(R.style.NightLargeTheme);
}
備註: 可能還有人會對"@dimen/standard_text_15" 以及 "@dimen/middle_text_15"有疑問,我是這樣計算的,根據三種字體大小: 16 18 23
,第二種級別字體是標準字體的1.125倍,第三種級別字體是標準字體的1.4375倍,那根據取捨便得標準、大號字體、超大號字體得dimens尺寸值:
<resources>
<dimen name="standard_text_15">15sp</dimen>
<dimen name="standard_text_17">17sp</dimen>
<dimen name="middle_text_15">16.8sp</dimen>
<dimen name="middle_text_17">19sp</dimen>
<dimen name="large_text_15">21.5sp</dimen>
<dimen name="large_text_17">24.4sp</dimen>
</resources>
綜上,上面的例子不但能實現字體大小跟隨主題切換同時也能實現日夜模式切換,但是這種方式感覺唯一不好的是自己得把每種字體的三種大小都定義在對應的主題裏,同時字體的三種字體大小值都得靠自己計算,這些操作起來可能會覺得繁瑣…