今天測試測出了一個問題,在高解析度下TextView的顯示沒問題,在低解析度出現了字型特別的小,也就是沒適配好。
左邊的是 768 * 1028 解析度的機子,右邊的是 1440 * 2560 解析度
推薦新聞部分是動態設定的TextView,出現了適配問題,然後來看看我的程式碼
第一次嘗試
TextView tv = new TextView(mContext);
tv.setTextSize(PixelUtils.sp2px(getContext(),4));
複製程式碼
這麼寫的思路是,螢幕都是以px為單位,文字大小用sp,我估摸著用sp的文字大小轉換成px設定到螢幕上,剛好適配,方案失敗。
第二次嘗試
TextView tv = new TextView(mContext);
tv.setTextSize(getResources().getDimensionPixelSize(R.dimen.sp_14));
複製程式碼
轉換有問題是吧,那我不轉換,我去dimens檔案裡面去取這個sp值,然後設定到介面上。
我靠,不至於吧,怎麼變這麼大,xml寫14sp的時候可是穩穩的
第三次嘗試
TextView tv = new TextView(mContext);
tv.setTextSize(13);
複製程式碼
實在無力了,隨便寫了算了,碰碰運氣,擦,居然可以,牛逼。
好奇的我就點進setTextSize方法裡面看了下原始碼,這才大悟恍然,先貼原始碼
@android.view.RemotableViewMethod
public void setTextSize(float size) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}
public void setTextSize(int unit, float size) {
Context c = getContext();
Resources r;
if (c == null)
r = Resources.getSystem();
else
r = c.getResources();
setRawTextSize(TypedValue.applyDimension(
unit, size, r.getDisplayMetrics()));
}
private void setRawTextSize(float size) {
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(size);
if (mLayout != null) {
nullLayouts();
requestLayout();
invalidate();
}
}
}
複製程式碼
setTextSize(float size)最終呼叫的是setTextSize(int unit,float size)方法,只是設定了一個預設引數TypedValue.COMPLEX_UNIT_SP,看引數名字是跟sp有關係
然後看setTextSize(int unit,float size)方法,判斷了下當前有沒有context上下文,然後拿到資源Resources,然後看下TypedValue.applyDimension(unit, size, r.getDisplayMetrics())
這個方法
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;
}
複製程式碼
我靠,好熟悉的程式碼,根據傳遞過來的unit,來分別計算出不同單位對應的畫素值是多少,跟我們的工具類PixelUtils.sp2px計算方法一模一樣,那些找畫素轉換還在百度和github的,這不都是現成的嘛,不僅僅有dp、sp的,還有pt、in和mm
然後我們回到setTextSize(float size)
方法,預設傳遞的TypedValue.COMPLEX_UNIT_SP,這一地方就是,你設定的size,我會幫你當做sp單位,然後轉換成px設定到螢幕上去,和我第一次嘗試的想法一樣,但是第一次為啥會失敗呢?
我們想想,我在呼叫PixelUtils.sp2px的時候進行了一次計算,這裡計算的結果我本來是想當做px用的,沒想到計算出來的結果直接被當做sp來用,然後通過setTextSize又進行了一次sp2px的計算,這個地方錯就錯在了第一次計算,因為第一次不同解析度下計算出來的sp2px是不一樣的,這個時候設定到螢幕上面去,肯定是完美的,但是,setTextSize對我們的計算結果又進行了一次sp2px,導致完美結果出錯,這就是我們為啥出錯了的原因。
第二次嘗試出錯就不說了,通過Resource拿到的dimen大小,最終會被轉換成px單位,就相當於sp2px(14),px都變得老老大了,然後當做sp一樣的去設定,肯定不對。
總結
1、這下知道了為啥TextView要用sp做單位了,就連setTextSize方法預設都是以sp來計算文字大小的。
2、不要相信群裡那些說不看原始碼的,說什麼面試看原始碼就是裝逼耍流氓的,告訴你,不看的話,你就是完蛋,問題都不知道怎麼解決
3、完畢,經理催我做專案了