最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android精確測(cè)量文本寬高及基線位置的方法

 更新時(shí)間:2018年08月14日 10:32:14   作者:orzangleli  
這篇文章主要給大家介紹了關(guān)于Android精確測(cè)量文本寬高及基線位置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

筆者最近在做一款彈幕控件,里面涉及到繪制文本,以及文本邊框。而繪制文本邊框需要知道文本的左邊位置,上邊位置,以及文本的寬高。

通常來(lái)說(shuō),使用 Canvas 繪制文本,可以通過(guò)畫(huà)筆 Paint 來(lái)設(shè)置文字的大小。但是畫(huà)筆的大小與文字的寬高并無(wú)直接關(guān)系。
大家應(yīng)該能說(shuō)上幾種測(cè)量文字寬高的方法,如:

方案1. 通過(guò) Paint 的 measureText 方法,可以測(cè)量文字的寬度

方案2. 通過(guò)獲取 Paint 的 FontMetrics, 根據(jù) FontMetrics 的 leading, ascent, 和 descent可以獲取文字的高度。

方案3. 通過(guò) Paint 的 getTextBounds 獲取文本的邊界矩形 Rect,根據(jù) Rect 可以計(jì)算出文字的寬高。

方案4. 通過(guò) Paint 獲取文字的 Path, 根據(jù) Path 獲取文本的邊界矩形 Rect, 根據(jù) Rect 可以計(jì)算出文字的寬高。

表面上看,我們有以上四種方案可以獲取文字的寬或高。但是不幸的,這四種方案里,有些方法獲取到的數(shù)值不是真實(shí)的文字寬高。

我們通過(guò)以下測(cè)試代碼,分別測(cè)試字母 "e" 和 "j"。

private void measureText(String str) {
 if (str == null) {
  return;
 }
 float width1 = mPaint.measureText(str);
 Log.i("lxc", "width1 ---> " + width1);

 Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
 float height1 = Math.abs(fontMetrics.leading + fontMetrics.ascent) + fontMetrics.descent;
 Log.i("lxc", "height1 ---> " + height1);

 Rect rect = new Rect();
 mPaint.getTextBounds(str, 0, str.length(), rect);
 float width2 = rect.width();
 float height2 = rect.height();
 Log.i("lxc", "width2 ---> " + width2);
 Log.i("lxc", "height2 ---> " + height2);


 Path textPath = new Path();
 mPaint.getTextPath(str, 0, str.length(), 0.0f, 0.0f, textPath);
 RectF boundsPath = new RectF();
 textPath.computeBounds(boundsPath, true);
 float width3 = boundsPath.width();
 float height3 = boundsPath.height();
 Log.i("lxc", "width3 ---> " + width3);
 Log.i("lxc", "height3 ---> " + height3);
}

調(diào)用以下代碼測(cè)試

measureText("e");
Log.i("lxc", " <----分割線----> ");
measureText("j");

日志輸出如下:

08-13 22:50:20.777 4977-4977/com.orzangleli.textbounddemo I/lxc: width1 ---> 21.0
08-13 22:50:20.777 4977-4977/com.orzangleli.textbounddemo I/lxc: height1 ---> 46.875
08-13 22:50:20.777 4977-4977/com.orzangleli.textbounddemo I/lxc: width2 ---> 18.0
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: height2 ---> 22.0
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: width3 ---> 17.929688
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: height3 ---> 21.914062
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc:  <----分割線---->
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: width1 ---> 10.0
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: height1 ---> 46.875
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: width2 ---> 8.0
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: height2 ---> 37.0
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: width3 ---> 8.046875
08-13 22:50:20.778 4977-4977/com.orzangleli.textbounddemo I/lxc: height3 ---> 37.36328

首先,我們可以確定字母 "e" 和 "j" 的顯示高度應(yīng)該不一樣,而使用第二種 FontMetrics 方案計(jì)算出的兩種情況文字高度一樣,而且從代碼的調(diào)用上看,我們也是直接根據(jù) Paint 獲取的 FontMetrics, 與文字內(nèi)容無(wú)關(guān)。所以我們需要測(cè)量文字真實(shí)高度的話,需要排除第二種方案了。

我們準(zhǔn)備一個(gè)自定義 View,在 onDraw 方法中使用 mPaint 繪制一個(gè)文本 "e", 然后截圖測(cè)量文本寬高,得出以下結(jié)果:

可以看到,文本的寬為 18, 高為 22。 可以得出以下結(jié)論:

方案1測(cè)量結(jié)果為近似值,存在一定誤差。

方案3測(cè)量結(jié)果準(zhǔn)確。

方案4測(cè)量結(jié)果精度更高,數(shù)值基本與方案3一致。

再多說(shuō)幾句。與測(cè)量文字高度類(lèi)似,我們?nèi)绾潍@取文字的基線 baseline 位置。

一般的博客上會(huì)告訴我們,如果需要計(jì)算文字的基線 baseline 位置,可以通過(guò) FontMetrics 來(lái)計(jì)算。FontMetrics 基線上面的值為負(fù)數(shù),基線下面的值為正數(shù)。baseline 計(jì)算公式為:

baseline = ascent + leading

如果你真的使用了這個(gè)公式就會(huì)發(fā)現(xiàn)坑。這個(gè)公式計(jì)算的基線位置實(shí)際上是默認(rèn)字體的基線位置,與文字內(nèi)容無(wú)關(guān)。我們可以看下面的例子:

在自定義 View 的 onDraw 方法中,繪制一個(gè)字符 "e", 繪制y坐標(biāo)為 baseline,所以文字應(yīng)該會(huì)頂著 Activity 的邊界。

@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);

 Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
 float baseline = Math.abs(fontMetrics.leading + fontMetrics.ascent);
 canvas.drawText("e", 0, baseline, mPaint);
}

顯示結(jié)果為:

那問(wèn)題來(lái)了,究竟怎么計(jì)算才能計(jì)算出真實(shí)的文本的基線位置呢。

我們使用之前的方案3來(lái)試試。代碼如下:

@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 String str = "e";
 Rect rect = new Rect();
 mPaint.getTextBounds(str, 0, str.length(), rect);
 float baseline = Math.abs(rect.top);
 canvas.drawText(str, 0, baseline, mPaint);
}

看看效果, 已經(jīng)能夠滿(mǎn)足我們的需求,左上都頂著 Activity 顯示了。

總結(jié)

精確測(cè)量文本寬高時(shí),盡量不要使用 FontMetrics 去做。如果要求不精確,可以使用 Paint 的 measureText 方法計(jì)算文本寬度,如果要求精確測(cè)量,可以使用 Paint 的 getTextBounds 方法 或者 getTextPath 方法,獲取文本的邊界框矩形 Rect, 所獲的Rect 的寬高即為文本的寬高, Rect的 top 為文本上邊界距基線的距離, Rect 的 bottom 為文本下邊距距離基線的距離。

本文涉及的代碼可以在我的 GitHub 項(xiàng)目 AndroidBlogDemo github.com/hust2010107 (本地下載)… 。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • BottomNavigationView?ViewPager2?Fragment底部菜單導(dǎo)航欄

    BottomNavigationView?ViewPager2?Fragment底部菜單導(dǎo)航欄

    這篇文章主要為大家介紹了BottomNavigationView?ViewPager2?Fragment底部菜單導(dǎo)航欄實(shí)現(xiàn)效果詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Android GridView仿微信朋友圈顯示圖片

    Android GridView仿微信朋友圈顯示圖片

    這篇文章主要介紹了Android GridView仿微信朋友圈顯示圖片,上傳多圖并且多圖顯示,GridView可以動(dòng)態(tài)加載圖片的數(shù)量,感興趣的小伙伴們可以參考一下
    2016-01-01
  • 史上最全的Android build.gradle配置教程

    史上最全的Android build.gradle配置教程

    這篇文章主要給大家介紹了關(guān)于Android build.gradle配置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • Android ProgressDialog的實(shí)例詳解

    Android ProgressDialog的實(shí)例詳解

    這篇文章主要介紹了Android ProgressDialog的實(shí)例詳解的相關(guān)資料,Android 開(kāi)發(fā)項(xiàng)目的時(shí)候經(jīng)常會(huì)遇到耗時(shí)的操作,這里就講下Android ProgressDialog的應(yīng)用,需要的朋友可以參考下
    2017-07-07
  • popupwindow焦點(diǎn)問(wèn)題解決方案

    popupwindow焦點(diǎn)問(wèn)題解決方案

    在android 開(kāi)發(fā)過(guò)程中,總會(huì)遇到一些問(wèn)題,比如popupwindow焦點(diǎn)問(wèn)題等等,我們?cè)撊绾谓鉀Q呢?需要的朋友可以了解下
    2012-11-11
  • Android 登錄Web 時(shí)對(duì)cookie 處理

    Android 登錄Web 時(shí)對(duì)cookie 處理

    本文主要介紹 Android登錄web時(shí)對(duì)cookie的處理方法,這里cookie 的讀寫(xiě)做了詳細(xì)介紹,并附有代碼進(jìn)行講解,希望能幫到有需要的同學(xué)
    2016-07-07
  • 在android中如何用Java加載解析so

    在android中如何用Java加載解析so

    我們?cè)赼ndroid開(kāi)發(fā)項(xiàng)目過(guò)程中都必然會(huì)更so加載打交道,那么so加載在系統(tǒng)中的順序和流程是怎樣的,我們就有必要對(duì)這個(gè)加載過(guò)程進(jìn)行熟悉了解掌握
    2021-10-10
  • Android中手機(jī)震動(dòng)的設(shè)置(Vibrator)的步驟簡(jiǎn)要說(shuō)明

    Android中手機(jī)震動(dòng)的設(shè)置(Vibrator)的步驟簡(jiǎn)要說(shuō)明

    Android中手機(jī)震動(dòng)的設(shè)置(Vibrator)的步驟,很詳細(xì),感興趣的朋友可以了解下哦
    2013-01-01
  • Android WebView 內(nèi)處理302重定向不跳轉(zhuǎn)的解決

    Android WebView 內(nèi)處理302重定向不跳轉(zhuǎn)的解決

    這篇文章主要介紹了Android WebView 內(nèi)處理302重定向不跳轉(zhuǎn)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03
  • Android中三種注入事件方法比較

    Android中三種注入事件方法比較

    這篇文章主要介紹了Android中三種注入事件方法比較,本文分別講解了使用內(nèi)部APIs、使用instrumentation對(duì)象、直接注入事件到設(shè)備/dev/input/eventX等3種方法,需要的朋友可以參考下
    2015-02-02

最新評(píng)論

惠来县| 雷州市| 龙井市| 河南省| 五原县| 宁南县| 新乐市| 恩平市| 纳雍县| 肥西县| 阳朔县| 镇远县| 鹿泉市| 英超| 太康县| 太白县| 兴城市| 泸定县| 安多县| 吴旗县| 勐海县| 林周县| 安义县| 大冶市| 张家界市| 大英县| 桃源县| 蓬莱市| 江陵县| 普洱| 馆陶县| 弥勒县| 本溪| 宕昌县| 监利县| 土默特右旗| 芷江| 神农架林区| 丹巴县| 新绛县| 惠东县|