[Android][canvas中drawText繪制文字垂直方向居中]

1. 落筆緣由

由于要實(shí)現(xiàn)類似注冊表單一樣瘪吏,文字作用兩端對齊的效果如下圖1铃彰,所以才有下面的內(nèi)容盏檐。

圖一 注冊表單

在canvas中歇式,調(diào)用drawText繪畫文字的時候,希望能夠在垂直方向居中畫出文字胡野。所以需要測量出要繪畫的文字的高材失。但具體來說,也不是獲取文字的高硫豆,因?yàn)槿绻怪本又挟嫵鑫淖至蓿捅仨毮玫轿淖值腷aseline,于是在網(wǎng)上搜索熊响,找到了一篇關(guān)于獲取baseline的文章(文章鏈接在本文底部列出)旨别,感覺就是我想要的,但是基于要懷疑一切的態(tài)度汗茄,不能你說是什么就是什么的秸弛,實(shí)踐才是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),所以下面我們來驗(yàn)證一下幾個觀點(diǎn)洪碳。

(1) 字體的5個位置是由使用的字體和字號決定的

首先可以明確递览,5個位置分別是top,ascent瞳腌,baseline绞铃,descent,bottom嫂侍。這五個位置受字號的大小影響是毋庸置疑的儿捧,這里不再討論冷离。這里驗(yàn)證了一下字體對五個位置的影響。字號默認(rèn)是16纯命,字體分別是系統(tǒng)默認(rèn)西剥,行書,小篆亿汞,方正姚體:
這5個位置分別用5條不同顏色的橫線條展示

  • top:淺灰色
  • ascent:黃色
  • baseline:紅色
  • descent:藍(lán)色
  • bottom:綠色

1)代碼展示

    private void init()
    {
        bodyLayout = new LinearLayout(this);
        if (bodyLayout != null)
        {
            llParams = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT);
            if (llParams!=null)
            {
                bodyLayout.setLayoutParams(llParams);
            }
            bodyLayout.setOrientation(LinearLayout.VERTICAL);
            bodyLayout.setBackgroundColor(Color.WHITE);
            //系統(tǒng)默認(rèn)字體
            MeasureText measureText = new MeasureText(this);
            if (measureText!=null)
            {
                llParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        Util.dip2px(this, 200));
                if (llParams!=null)
                {
                    measureText.setLayoutParams(llParams);
                }
                bodyLayout.addView(measureText);
            }
            //行書
            MeasureText measureText2 = new MeasureText(this);
            if (measureText2!=null)
            {
                llParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        Util.dip2px(this, 200));
                if (llParams!=null)
                {
                    measureText2.setLayoutParams(llParams);
                }
                Typeface face = Typeface.createFromAsset (getAssets() , "fonts/xs.ttf" );
                measureText2.setFace(face);
                
                bodyLayout.addView(measureText2);
            }
            //小篆
            MeasureText measureText3 = new MeasureText(this);
            if (measureText3!=null)
            {
                llParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        Util.dip2px(this, 200));
                if (llParams!=null)
                {
                    measureText3.setLayoutParams(llParams);
                }
                Typeface face = Typeface.createFromAsset (getAssets() , "fonts/fzxz.TTF" );
                measureText3.setFace(face);
                
                bodyLayout.addView(measureText3);
            }
            //方正姚體
            MeasureText measureText4 = new MeasureText(this);
            if (measureText4!=null)
            {
                llParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        Util.dip2px(this, 200));
                if (llParams!=null)
                {
                    measureText4.setLayoutParams(llParams);
                }
                Typeface face = Typeface.createFromAsset (getAssets() , "fonts/fzyt.TTF" );
                measureText4.setFace(face);
                
                bodyLayout.addView(measureText4);
            }
        }
    }

2)效果演示

圖2 字體對top瞭空,ascent,baseline疗我,descent咆畏,bottom文字影響

3)結(jié)果

從效果看,字體對top吴裤,ascent旧找,baseline,descent麦牺,bottom的位置影響并不明顯钮蛛。

(2)以baseline為基準(zhǔn),向上為負(fù)剖膳,向下為正魏颓。ascent為負(fù)數(shù),descent為正數(shù)吱晒。

通過Log打印的日志可以得出結(jié)果

圖3 Log日志

結(jié)果:以baseline為基準(zhǔn)線甸饱,向上為負(fù),向下為正是正確的仑濒。

(3)如果嘗試將兩個TextView上下排列叹话,沒有margin和padding,兩個TextView文字之間依然有空隙墩瞳。首先我們需要設(shè)置includeFontPadding為false驼壶!但是依然有空隙,這時的空隙就是由top與ascent之間的空隙和bottom與descent直接的空隙造成的了矗烛。這個就不用例子驗(yàn)證了辅柴,不然怎么解釋這個空隙的存在。

(4)baseline = (mHeight - (mFontMetricsInt.descent - mFontMetricsInt.ascent)) / 2 - mFontMetricsInt.ascent

這個不是驗(yàn)證了瞭吃,說了那么多也就是為了如何在垂直方向居中繪制文字,關(guān)鍵在于獲取baseline位置涣旨。Canvas中的drawText中繪制文字的基準(zhǔn)線是baseline歪架。

baseline = (mHeight - (mFontMetricsInt.descent - mFontMetricsInt.ascent)) / 2 - mFontMetricsInt.ascent

使得ascent到View的是上邊距與descent到View下邊距距離一致即可,此段距離加上ascent的絕對值(-ascent)即為baseline的位置霹陡。

2. 總結(jié)

在Canvas中使用drawText繪制垂直居中文字的關(guān)鍵在于求出baseline的位置和蚪。獲取位置的公式:

baseline = (mHeight - (mFontMetricsInt.descent -
         mFontMetricsInt.ascent)) / 2 - mFontMetricsInt.ascent
即baseline = (mHeight - mFontMetricsInt.ascent -mFontMetricsInt.descent) 
/ 2

3. 源碼地址

https://github.com/lgygg/MeasureHeight

4. 參考文章

http://blog.csdn.net/su1216/article/details/46900617#

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末止状,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子攒霹,更是在濱河造成了極大的恐慌怯疤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件催束,死亡現(xiàn)場離奇詭異集峦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)抠刺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進(jìn)店門塔淤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人速妖,你說我怎么就攤上這事高蜂。” “怎么了罕容?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵备恤,是天一觀的道長。 經(jīng)常有香客問我锦秒,道長烘跺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任脂崔,我火速辦了婚禮滤淳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砌左。我一直安慰自己脖咐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布汇歹。 她就那樣靜靜地躺著屁擅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪产弹。 梳的紋絲不亂的頭發(fā)上派歌,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天,我揣著相機(jī)與錄音痰哨,去河邊找鬼胶果。 笑死,一個胖子當(dāng)著我的面吹牛斤斧,可吹牛的內(nèi)容都是我干的早抠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼撬讽,長吁一口氣:“原來是場噩夢啊……” “哼蕊连!你這毒婦竟也來了悬垃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤甘苍,失蹤者是張志新(化名)和其女友劉穎尝蠕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體载庭,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡看彼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了昧捷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闲昭。...
    茶點(diǎn)故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖靡挥,靈堂內(nèi)的尸體忽然破棺而出序矩,到底是詐尸還是另有隱情,我是刑警寧澤跋破,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布簸淀,位于F島的核電站,受9級特大地震影響毒返,放射性物質(zhì)發(fā)生泄漏租幕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一拧簸、第九天 我趴在偏房一處隱蔽的房頂上張望劲绪。 院中可真熱鬧,春花似錦盆赤、人聲如沸贾富。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颤枪。三九已至,卻和暖如春淑际,著一層夾襖步出監(jiān)牢的瞬間畏纲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工春缕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盗胀,地道東北人。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓淡溯,卻偏偏與公主長得像读整,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咱娶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容