問幾個(gè)問題先
在app/src/main/res/values/dimens.xml中定義尺寸如下:
<dimen name="font1">18sp</dimen>
在代碼中引用此尺寸如下:
mText.setTextSize(18); // 方法1
mText.setTextSize(getResources().getDimension(R.dimen.font1)); // 方法2
mText.setTextSize(TypedValue.COMPLEX_UNIT_PX,getResources().getDimension(R.dimen.font1)); // 方法3
mText.setTextSize(TypedValue.COMPLEX_UNIT_SP,18); // 方法4
問題1: 方法1和方法2設(shè)置的文字尺寸大小相同么?
問題2:方法3和方法4設(shè)置的文字尺寸大小相同么甘穿?
問題3:方法1和方法4設(shè)置的文字尺寸大小相同么机久?
如果你能很清楚的給出上面問題的答案仓洼,那就沒必要再向下看了矢腻;
如果你對(duì)以上問題感到模棱兩可的話煌张,請(qǐng)繼續(xù)往下看:
要想解開以上疑惑早歇,其實(shí)主要從以下兩個(gè)方法的源碼入手
setTextSize(...)
進(jìn)入TextView類焰檩,找到setTextSize(...)方法憔涉,發(fā)現(xiàn)它調(diào)用了另一個(gè)重載方法,注意這里調(diào)用重載方法時(shí)傳入的第一個(gè)參數(shù)是一個(gè)默認(rèn)值 TypedValue.COMPLEX_UNIT_SP析苫,因此方法1和方法4設(shè)置的文字尺寸大小相同.
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()));
}
重載方法中有兩個(gè)方法需要重點(diǎn)看
setRawTextSize(...)方法
通過它的幾個(gè)方法會(huì)發(fā)現(xiàn)它的作用就是真正設(shè)置文字大小并刷新顯示:
private void setRawTextSize(float size) {
if (size != mTextPaint.getTextSize()) {
mTextPaint.setTextSize(size);
if (mLayout != null) {
nullLayouts();
requestLayout();
invalidate();
}
}
}
TypedValue類中的applyDimension(...)方法
根據(jù)傳入的unit單位來處理文字大小兜叨,返回的尺寸為px (通過第一個(gè)case條件得知).
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為COMPLEX_UNIT_PX穿扳,則會(huì)將value直接返回
如果傳入的unit為COMPLEX_UNIT_SP,則會(huì)將value處理成px返回
getDimension(...)
進(jìn)入Resources類国旷,找到getDimension(...)方法
public float getDimension(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
mTmpValue = value = new TypedValue();
}
getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimension(value.data, mMetrics);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id) + " type #0x" + Integer.toHexString(value.type) + " is not valid");
}
}
這里方法不多矛物,點(diǎn)getValue(...)方法進(jìn)去看會(huì)發(fā)現(xiàn)它內(nèi)部又調(diào)用了native方法,這里我無法進(jìn)一步追溯它的實(shí)現(xiàn)跪但,不過沒關(guān)系履羞,因?yàn)槲野l(fā)現(xiàn)有個(gè)方法很眼熟那就是:TypedValue.complexToDimension(...) ,進(jìn)入此方法會(huì)驚奇的發(fā)現(xiàn)它也調(diào)用了上面講到的applyDimension(...)方法.
public static float complexToDimension(int data, DisplayMetrics metrics){
return applyDimension(
(data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, complexToFloat(data), metrics);
}
由此可以大膽的猜測(cè) getDimension(...)方法最終也會(huì)將數(shù)據(jù)處理成px返回屡久,因此方法3和方法4設(shè)置的文字尺寸大小相同忆首,只是寫法不同而已.
好了,回到開篇提到的四個(gè)問題被环,可以得出以下結(jié)論:
方法1:文字尺寸以sp為單位糙及,大小為18
方法2:文字尺寸以sp為單位,大小為(18sp轉(zhuǎn)換為px的值)
方法3:文字尺寸以px為單位蛤售,大小為(18sp轉(zhuǎn)換為px的值)
方法4:文字尺寸以sp為單位丁鹉,大小為18
方法1=方法3=方法4!=方法2
至此妒潭,文章結(jié)束悴能,希望此文能幫助到你,如果對(duì)此文有不同見解雳灾,歡迎直接評(píng)論漠酿!