文本結(jié)構(gòu)
其實(shí)是沒有文本結(jié)構(gòu)這個(gè)概念的,所謂的文本結(jié)構(gòu)篮赢,是作者定義出來的用來描述文本繪制到顯示屏的一個(gè)概念齿椅,其中包含著BaseLine、Ascent启泣、Descent涣脚、Leading。
BaseLine也就是我們常說的基線寥茫,Ascent遣蚀、Descent、以及Leading這些都是字體設(shè)計(jì)的規(guī)范纱耻。
現(xiàn)實(shí)現(xiàn)一個(gè)計(jì)步器芭梯,效果圖如下:
看起來實(shí)現(xiàn)很簡單,在onDraw方法上膝迎,先勾畫出一個(gè)圓粥帚,然后在此區(qū)域上再畫出一段弧出來,最后將文本繪制上去限次。
代碼如下
paint.setStyle(Paint.Style.STROKE);
paint.setColor(CIRCLECOLOR);
paint.setStrokeWidth(RING_WIDTH);
canvas.drawCircle(getWidth()/2,getHeight()/2,RADIUS,paint);
paint.setColor(Color.GREEN);
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawArc(getWidth()/2-RADIUS,getHeight()/2-RADIUS,
getWidth()/2+RADIUS,getHeight()/2+RADIUS,-90,225,
false,paint);
paint.setTextSize(140);
paint.setStyle(Paint.Style.FILL);
paint.setTextAlign(Paint.Align.CENTER);
paint.getTextBounds(demoString,0,demoString.length(),bounds);
canvas.drawText(demoString,getWidth()/2,getHeight()/2,paint);
運(yùn)行后的效果:
可以發(fā)現(xiàn)芒涡,即使我們設(shè)置了Paint.Align.CENTER的屬性,雖然在水平方向上卖漫,文本是劇中的费尽,但是在豎直方向上,文本是有所偏移的羊始。
那么問題就來了旱幼,這是Bug嗎?
不是突委,因?yàn)槲覀兪前凑誂ndroid的APi寫出來的柏卤,這既不是我們的Bug也不是Google的Bug,當(dāng)然產(chǎn)品驗(yàn)收的時(shí)候冬三,會十分肯定地跟你說,你這是個(gè)Bug缘缚。
為什么說這不是Bug呢勾笆?
仔細(xì)一看,你就會發(fā)現(xiàn)桥滨,文本底部穿過圓心窝爪。
BaseLine的位置剛好是居中的,文本繪制是以BaseLine的縱坐標(biāo)開始繪制的齐媒。所以我們只需要將BaseLine的位置減去一個(gè)偏移量蒲每,就可以獲得偏移之后的BaseLine的位置,文本也就能居中了喻括。
偏移就是文本長度的一半邀杏,如何獲得?
這里有兩種方法唬血。
1淮阐、通過文本繪制區(qū)域獲取
文本在繪制過程中,本就是一塊矩形區(qū)域刁品。所以可以通過獲得文本繪制區(qū)域的top與bottom的差泣特,來得到偏移量。
Rect bounds=new Rect();//1
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
paint.getTextBounds(demoString,0,demoString.length(),bounds);
float offest=(bounds.top + bounds.bottom)/2;
canvas.drawText(demoString,getWidth()/2,getHeight()/2-offest,paint);
}
注釋1通過實(shí)例化一個(gè)Rect對象挑随,再通過Paint的getTextBounds方法計(jì)算獲得Rect的值状您。
但是利用Rect獲得的偏移去實(shí)現(xiàn)居中,在列表滾動的時(shí)候居中文字會出現(xiàn)跳動兜挨,因?yàn)椴煌奈谋镜腞ect是不一樣的膏孟,雖然最后都能實(shí)現(xiàn)居中,但是在產(chǎn)品看來拌汇,這是屬于不穩(wěn)定的柒桑,甚至是一個(gè)Bug。
2噪舀、利用Ascent與Descent
由于Ascent與Descent是字體級別的設(shè)置魁淳,動態(tài)的文本并不會導(dǎo)致這個(gè)兩個(gè)值變動。通過Ascent與Descent拿到的偏移与倡,是穩(wěn)定的界逛,不變的。同時(shí)纺座,它的偏移計(jì)算只計(jì)算一次就可以了息拜,并不用放到onDraw方法里,我們通過FontMetrics來獲得這些數(shù)值。
Paint.FontMetrics fontMetrics=new Paint.FontMetrics();//1
String demoString="12030步";
{
paint.setTextSize(200);
paint.setTextAlign(Paint.Align.CENTER);
paint.getFontMetrics(fontMetrics);//2
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
float offest=(fontMetrics.ascent+ fontMetrics.descent)/2;
canvas.drawText(demoString,getWidth()/2,getHeight()/2-offest,paint);
}
}
在注釋1可以看到FontMetrics是Paint的一個(gè)靜態(tài)類少欺,在注釋2里面通過getFontMetrics計(jì)算得到FontMetrics的值喳瓣。