Android之玩轉(zhuǎn)View(三):使用Paint實(shí)現(xiàn)的文字繪制(文字的基線(xiàn))

使用Paint實(shí)現(xiàn)的文字繪制(文字的基線(xiàn))

請(qǐng)尊重原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處【tianyl】的博客

關(guān)于的Android之玩轉(zhuǎn)View目錄

前言

上篇文章介紹了一些使用Paint和Shader結(jié)合實(shí)現(xiàn)的一些特效熄云,不過(guò)都是一些圖像繪制方面的舶沛,當(dāng)然匀借,Paint除了能夠進(jìn)行圖像繪制之外误墓,還有另外一個(gè)功能偎漫,就是文字的繪制

當(dāng)然,在學(xué)習(xí)Paint繪制文字之前尔邓,最好能夠熟悉一些Paint繪制文字的api這是Paint繪制文字的常用api說(shuō)明

1 文字的基線(xiàn)

說(shuō)到文字繪制晾剖,先從一個(gè)api說(shuō)起

drawText(@NonNull String text, float x, float y, @NonNull Paint paint)

這是一個(gè)常用的繪制文字的辦法,可能有朋友會(huì)遇到梯嗽,在使用這個(gè)方法繪制文字的時(shí)候钞瀑,文字的位置經(jīng)常不對(duì),不是高了慷荔,就是低了雕什,這就是由于這個(gè)api中的x和y造成的

看圖說(shuō)明


在我們繪制文字的時(shí)候,通常有上圖中的六條線(xiàn)显晶,分別是

  1. top:頂點(diǎn)線(xiàn)
  2. ascent:建議頂點(diǎn)線(xiàn)
  3. center:中心線(xiàn)
  4. baseline:基線(xiàn)
  5. descent:建議底部線(xiàn)
  6. bottom:底部線(xiàn)

這六條線(xiàn)分別起什么作用呢贷岸?

  • 首先是top和bottom,這兩條線(xiàn)很好理解磷雇,它分別是頂端和底端偿警,繪制文字時(shí)肯定不會(huì)超過(guò)這兩條線(xiàn)
  • 然后是ascent和descent,這兩條線(xiàn)是建議的頂點(diǎn)線(xiàn)和建議底端線(xiàn)唯笙,一般情況我們繪制文字是不會(huì)超過(guò)這兩條線(xiàn)的螟蒸,但是對(duì)于一些異形字(論壇中經(jīng)常出現(xiàn)的跨樓層的字)是可以超出這兩條線(xiàn)的
  • 再則是center線(xiàn),這條線(xiàn)也很好理解崩掘,它就是top和bottom的中心
  • 最后就是基線(xiàn)了七嫌,這也是我們繪制文字時(shí),傳入的y坐標(biāo)

1.1 基線(xiàn)的計(jì)算

解釋了上面六條線(xiàn)的作用苞慢,接下來(lái)再說(shuō)說(shuō)這六條線(xiàn)是怎么計(jì)算的诵原。

首先,我們要清楚挽放,這六條線(xiàn)都是真實(shí)存在的绍赛,它們的值就保存在Paint.FontMetricsPaint.FontMetricsInt中,這兩個(gè)類(lèi)的值基本相似辑畦,區(qū)別是一個(gè)是float吗蚌,一個(gè)是int

如圖

  • Paint.FontMetrics


  • Paint.FontMetricsInt


明確了這六條線(xiàn)值的位置,那它們是怎么計(jì)算得來(lái)的呢纯出?

首先說(shuō)明蚯妇,計(jì)算著六條線(xiàn)的時(shí)候,是以基線(xiàn)為參照物的潦刃,計(jì)算方式如下

注:在以下計(jì)算推斷中侮措,ascent,desent之類(lèi)的都表示距離乖杠,ascent.y分扎,desent.y之類(lèi)的表示坐標(biāo)

top.y = top.y - baseline.y
bottom.y = bottom.y - baseline.y
ascent.y = ascent.y - baseline.y
desent.y = desent.y - baseline.y
center.y = (bottom.y - top.y) / 2

因?yàn)槭且詁aseline為參照物,所以所有的距離都是它們的y坐標(biāo)和baseline的y坐標(biāo)相減胧洒,
但是Paint.FontMetrics中并沒(méi)有baseline的值畏吓,那么我們要怎么得到它呢

baseline的計(jì)算如圖所示(網(wǎng)上好多圖都是錯(cuò)的墨状,不得不自己畫(huà)了一張,(╥﹏╥))

首先菲饼,如果我們要繪制文本肾砂,那么我們可以拿到top和bottom的坐標(biāo),并且我們也知道center

  • center.y = (bottom.y - top.y) / 2

看圖宏悦,我們知道top.y到center.y的距離和bottom.y到center.y的距離相同镐确,設(shè)定這個(gè)距離為a,那么center.y到baseline.y的距離就是:a - bottom
(沒(méi)有.y時(shí)表示它到baseline的距離)

所以有:

  • baseline.y - center.y = (bottom.y - top.y) / 2 - bottom.y

解得:

  • baseline.y = center.y + (bottom.y - top.y) / 2 - bottom.y

當(dāng)然饼煞,同樣的推理源葫,還可以得出baseline和ascent,desent之間的關(guān)系砖瞧,這里就不展開(kāi)了息堂,原理都是一樣的

1.2 如何繪制文字到中心

經(jīng)歷了前面的長(zhǎng)篇大論,有的同學(xué)就要問(wèn)了块促,知道baseline的計(jì)算有什么用呢荣堰?

回到最開(kāi)始的api

drawText(@NonNull String text, float x, float y, @NonNull Paint paint)

是不是有的同學(xué)在使用這個(gè)api的時(shí)候,經(jīng)常遇到y(tǒng)值怎么設(shè)置都不能讓文字處于控件中間竭翠,不是高一點(diǎn)就是低一點(diǎn)振坚?

如果我們想把文字繪制到我們View的正中心,那么這里的y就需要傳入我們計(jì)算好的baseline逃片,代碼如下

// 首先設(shè)置paint的文字大小
paint.setColor(textColor);
paint.setStrokeWidth(0);
paint.setTextSize(textSize);
paint.setTypeface(Typeface.DEFAULT_BOLD);

//根據(jù)paint的文字大小獲得Paint.FontMetricsInt
Paint.FontMetricsInt fm = paint.getFontMetricsInt();

//根據(jù)Paint.FontMetricsInt計(jì)算baseline
canvas.drawText(string, getWidth() / 2 - paint.measureText(string) / 2 ,
            getHeight() / 2  +(fm.bottom - fm.top)/2 - fm.bottom, paint);

這樣屡拨,就可以將文字畫(huà)到垂直方向的正中心了,至于水平中心褥实,只需要控件寬度減去文字寬度除以2就可以了

本來(lái)還想寫(xiě)一些文字的特效的,想來(lái)篇幅太長(zhǎng)閱讀起來(lái)體驗(yàn)也不太好裂允,文字的特效就留到以后寫(xiě)吧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末损离,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子绝编,更是在濱河造成了極大的恐慌僻澎,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件十饥,死亡現(xiàn)場(chǎng)離奇詭異窟勃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)逗堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)秉氧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蜒秤,你說(shuō)我怎么就攤上這事汁咏⊙钦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵攘滩,是天一觀(guān)的道長(zhǎng)帅刊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)漂问,這世上最難降的妖魔是什么赖瞒? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮蚤假,結(jié)果婚禮上冒黑,老公的妹妹穿的比我還像新娘。我一直安慰自己勤哗,他們只是感情好抡爹,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著芒划,像睡著了一般冬竟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上民逼,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天泵殴,我揣著相機(jī)與錄音,去河邊找鬼拼苍。 笑死笑诅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疮鲫。 我是一名探鬼主播吆你,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俊犯!你這毒婦竟也來(lái)了妇多?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤燕侠,失蹤者是張志新(化名)和其女友劉穎者祖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绢彤,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡七问,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茫舶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片械巡。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出坟比,到底是詐尸還是另有隱情芦鳍,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布葛账,位于F島的核電站柠衅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏籍琳。R本人自食惡果不足惜菲宴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趋急。 院中可真熱鬧喝峦,春花似錦、人聲如沸呜达。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查近。三九已至眉踱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間霜威,已是汗流浹背谈喳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戈泼,地道東北人婿禽。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像大猛,于是被迫代替她去往敵國(guó)和親扭倾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361