Android文字繪制 -- 怎樣理解“基線”

2018-06-15

首先我們看看怎樣在Android中繪制出文字 以及與可以方便我們理解基線的其它線條
如何在android的View控件中繪制文字:
重寫(xiě)View的onDraw方法 使用其Canvas類(lèi)的方法 canvas.drawText();

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawText("jaeger",measureWidth / 2,measureHeight / 2,texPaint);//文字

    canvas.drawLine(0,measureHeight / 2,measureWidth,measureHeight / 2,centerLineP);//屏幕中線

    canvas.drawLine(0,measureHeight / 2 + (top + bottom) / 2,measureWidth,measureHeight / 2 + (top + bottom) / 2,texCenterLineP);//文字中線

    canvas.drawLine(0,measureHeight / 2 + top,measureWidth,measureHeight / 2 + top,topLineP);//文字頂線

    canvas.drawLine(0,measureHeight / 2 + bottom,measureWidth,measureHeight / 2 + bottom,bottomLineP);//文字頂線

    canvas.drawLine(0,measureHeight / 2 - 400,measureWidth,measureHeight / 2 - 400,halfLineP);//屏幕上分隔線
    canvas.drawLine(0,measureHeight / 2 + 400,measureWidth,measureHeight / 2 + 400,halfLineP);//屏幕下分隔線
}

其中measureWidth與measureHeight是手機(jī)屏幕的寬和高

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY)
        measureWidth = MeasureSpec.getSize(widthMeasureSpec);
    if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY)
        measureHeight = MeasureSpec.getSize(heightMeasureSpec);
    setMeasuredDimension(measureWidth,measureHeight);
}

參數(shù)初始化方法

private void init(){
    texPaint = new Paint();//文字畫(huà)筆
    texPaint.setTextSize(300);
    texPaint.setColor(Color.BLACK);
    texPaint.setTextAlign(Paint.Align.CENTER);
    texPaint.setTypeface(Typeface.DEFAULT_BOLD);

    centerLineP = new Paint();//屏幕中線畫(huà)筆
    centerLineP.setStrokeWidth(15);
    centerLineP.setColor(Color.RED);

    topLineP = new Paint();//文字頂線畫(huà)筆
    topLineP.setStrokeWidth(15);
    topLineP.setColor(Color.GREEN);

    bottomLineP = new Paint();//文字底線畫(huà)筆
    bottomLineP.setStrokeWidth(15);
    bottomLineP.setColor(Color.YELLOW);

    texCenterLineP = new Paint();//文字中線畫(huà)筆
    texCenterLineP.setStrokeWidth(5);
    texCenterLineP.setColor(Color.BLACK);

    halfLineP = new Paint();//分隔線畫(huà)筆
    halfLineP.setStrokeWidth(15);
    halfLineP.setColor(Color.MAGENTA);

    Paint.FontMetricsInt fontMetricsInt = texPaint.getFontMetricsInt();
    top = fontMetricsInt.top;
    bottom = fontMetricsInt.bottom;
    baseLine = (bottom - top) / 2 - bottom;//文字基線
}

最終獲取的效果如下:


效果圖

現(xiàn)在我們來(lái)談?wù)勊^的文字“基線”是什么
文字的“基線”就如同是我們的英語(yǔ)寫(xiě)字用的“四線本” 實(shí)際上我們正式寫(xiě)字的時(shí)候?yàn)榱苏麧?都是有一條線的

文字

所以我們可以發(fā)現(xiàn)在“效果圖”上 文字和上述何等相似:a e r等單字都排布在基線上 而j g卻超出了基線 但是g這個(gè)字在上半部分也是老實(shí)地排布在基線上 這和我們寫(xiě)英文字時(shí)的習(xí)慣是一模一樣的

android文字的繪制也以使用了同樣的方法使繪制出的文字保證整齊劃一地排布:給文字定了一條基準(zhǔn)線 而我們上述通過(guò)Paint.FontMetricsInt 獲取的top和bottom值就與基線有關(guān)

示例

圖片來(lái)源:https://blog.csdn.net/hailuoli/article/details/78558594

在我的手機(jī)上 top 為 - 317 bottom 為 82 計(jì)算出基線(偏移)為117
這里的top和bottom的值 實(shí)際是基于基線而得 可理解為 以文字基線為準(zhǔn) 向上平移317像素為繪制區(qū)域的頂 向下平移82像素為繪制區(qū)域的底(基線向上為負(fù) 向下為正)

已知基線與繪制區(qū)頂相距317 與底相距82 得繪制區(qū)高度 bottom - top:82 - (-317) = 399
繪制區(qū)中線高度為(bottom - top)/ 2 : 399 / 2 = 199 (int)
繪制區(qū)中線高度等價(jià)于 中線與繪制區(qū)底 之間的距離 這個(gè)距離減去 基線與繪制區(qū)底 之間的距離 就是中線與基線之間的距離 (bottom - top) / 2 - bottom : 199 - 82 = 117

那這個(gè)值和我們?cè)赼ndroid中繪制文字有什么關(guān)系呢卿操?
關(guān)鍵在于 我們?cè)谏鲜龃a中 drawText傳入的y值是屏幕的高 / 2 因?yàn)槲覀兿M淖挚梢猿霈F(xiàn)在屏幕的中間 但是事與愿違 我們的文字很明顯沒(méi)有出居中于屏幕

--因?yàn)?drawText中傳入的Y的實(shí)際意義是文字的基線所在的位置--

我們將文字的基線放在了屏幕中間 文字在繪制出來(lái)時(shí)當(dāng)然不會(huì)居中于屏幕 -- 我們應(yīng)該將文字的中線放在屏幕的中間 這樣文字在繪制出來(lái)時(shí)就可以居中了

因?yàn)橐婚_(kāi)始我們傳的y實(shí)際是文字基線將要所在的位置 現(xiàn)在我們想傳入的y應(yīng)該是中線的位置 上面我們得到中線和基線的距離是117 所以應(yīng)該以之前的y + 117(baseLine 基線偏移值):

    canvas.drawText("jaeger",measureWidth / 2,measureHeight / 2 + baseLine,texPaint);
效果

當(dāng)然 明白了基線的作用和使用方法 那我們已應(yīng)該可以處理這種問(wèn)題:

    canvas.drawText("jaeger",measureWidth / 2,0 + baseLine,texPaint);//文字
不完全顯示

經(jīng)常繪制文字發(fā)現(xiàn)考慮基線偏移是很常見(jiàn)的問(wèn)題
這時(shí)應(yīng)該這樣:

    canvas.drawText("jaeger",measureWidth / 2,-top,texPaint);//文字

文字顯示完整了


完全顯示

當(dāng)然 文字繪制的參考線不只有top 和 bottom跟匆,還有ascent;descent;leading 參見(jiàn)“示例”圖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挺邀,隨后出現(xiàn)的幾起案子判呕,更是在濱河造成了極大的恐慌品嚣,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件求冷,死亡現(xiàn)場(chǎng)離奇詭異瘤运,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)匠题,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)拯坟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人韭山,你說(shuō)我怎么就攤上這事郁季±淅#” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵梦裂,是天一觀的道長(zhǎng)似枕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)年柠,這世上最難降的妖魔是什么凿歼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮冗恨,結(jié)果婚禮上答憔,老公的妹妹穿的比我還像新娘。我一直安慰自己掀抹,他們只是感情好虐拓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著傲武,像睡著了一般蓉驹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揪利,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天戒幔,我揣著相機(jī)與錄音,去河邊找鬼土童。 笑死,一個(gè)胖子當(dāng)著我的面吹牛工坊,可吹牛的內(nèi)容都是我干的献汗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼王污,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼罢吃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起昭齐,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤尿招,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后阱驾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體就谜,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年里覆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丧荐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喧枷,死狀恐怖虹统,靈堂內(nèi)的尸體忽然破棺而出弓坞,到底是詐尸還是另有隱情,我是刑警寧澤车荔,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布渡冻,位于F島的核電站,受9級(jí)特大地震影響忧便,放射性物質(zhì)發(fā)生泄漏族吻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一茬腿、第九天 我趴在偏房一處隱蔽的房頂上張望呼奢。 院中可真熱鬧,春花似錦切平、人聲如沸握础。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)禀综。三九已至,卻和暖如春苔严,著一層夾襖步出監(jiān)牢的瞬間定枷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工届氢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欠窒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓退子,卻偏偏與公主長(zhǎng)得像岖妄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寂祥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353