Android中文圖混排時文圖的居中對齊 FontMetrics以及自定義ImageSpan實現

文章轉自:http://www.sohu.com/a/150059234_611601

?

本文作者CnPeng的博客地址:

http://www.jianshu.com/p/2650357f7547

這個標題有點長,乍一看這么個標題你可能沒明白啥意思,且聽我慢慢道來。

公司的項目中新增了一個“心動” 的功能,用戶初次使用時需要給一個引導頁,就是下面圖中的這個樣子(這就是做完之后的效果了)。

在上圖中整體實現的時候使用的是popUpWindow。

該popupWindow整體使用相對布局,里面再用一個相對布局布局嵌套了三個TextView:"啊哦。。。。pass" 用一個TextView,中間灰色的上傳頭像的提示用了一個TextView,底部“我知道了” 也是一個TextView。

上面的左劃示意圖使用above 放在 包含TextView的相對布局上方,并通過負的margin值將它下移并覆蓋在包含TextView相對布局上。

這個界面并沒有什么難度,這里重點說的是第一個TextView中的圖文混排,并讓圖片的橫向中間線與該行文字的橫向中間線對齊,也就是說,讓文字與那個�� 圖片的中間在水平方向對齊。

1

圖文混排的方式有哪些?

通常我們向TextView中插入圖片實現圖文混排有如下方式:

1. 使用drawableLeft等屬性設置,這種方式對應的java方法是 setCompoundDrawablesWithIntrinsicBounds(leftDrawble,topDrawable,rightDrawable,bottomDrawable);

2. 使用 SpannableString ,先將圖片轉成ImageSpan對象,然后通過setSpan插入到SpannableString 中,最后再將SpannableString通過setText設置給TextView。(SpannableString 繼承自CharSquence)

3. 此外,還有一種利用Html.ImageGetter格式化圖片的方式。(截止目前為止,我沒用過這種方式,如果想了解的話,可以參考http://wangleyiang.iteye.com/blog/1771439中的第二點)

2

使用SpannableString+ImageSpan怎么實現圖文混排?

(1)基本實現方式

效果圖如下:

實現方式很簡單,我們只需要在xml布局文件中定義一個TextView,然后在代碼中獲取該TextView并創建一個含有圖片的SpannableString,并將該SpannableString通過setText( )設置給TextView即可。

代碼如下:

xml布局文件中只給了一個普通的TextView,代碼省略。

在上面的代碼中,我們通過ImageSpan的構造方法得到了一個ImageSpan對象。該構造方法中傳入的兩個參數分別是上下文和圖片的id。(imageSpan的構造方法還有很多)

SpannbaleString的setSpan方法中,傳入的四個參數分別是 ImageSpan對象、將ImageSpan插入到的起始位置(start)、將ImageSpan插入到的終點位置(end)、是否應用字體樣式。

具體將ImageSpan對象插入到哪個位置,由第二個和第三個參數確定,插入的時候會覆蓋從 start 位置開始(不包含該位置)到終止位置間的內容(包含該位置)。

第四個參數是在你插入文本的時候使用的,用來控制新插入的文本與已有文本內容的字體樣式是否一致的如果你插入的是圖片,這里就可以隨便選擇一種模式。

經過上面雖然實現了圖文混排,但是,細心的你可能發現了,這時候的文字和圖片是基于底部對齊的(由于圖片的原因,圖片底部與邊框有一點點的間距)。那么如果我想更改對齊方式怎么辦呢?

(2)更改圖片與文本的對齊方式--ALIGN_BASELINE對齊

設置對齊方式的方法很簡單,在構造ImageSpan對象的時候,傳入第三個參數ALIGN_BASELINE 即可,代碼如下:

ImageSpan imageSpan = new ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE);

設置對齊方式為ALIGN_BASELINE后的效果圖:

咦,看著跟上面的圖沒啥區別啊?那么我再把上面沒設置對齊方式的圖拉下來看下:

仔細對比下,我們發現,設置對齊方式之后,圖往上跑了一點點。

其實,在ImageSpan 中,官方只給出了兩中對齊方式:

  1. 一種是 ALIGN_BOTTOM , 表示與文字內容的底部對齊,如果在構造ImageSpan時沒有傳入對齊方式,那么默認就是這種底部對齊。

  2. 另一中就是 ALIGN_BASELINE, 表示與文字內容的基線對齊。那么,你可能會問我基線是啥?請繼續往下看:

3

Paint.FontMetrics 是啥?

(1) Paint.FontMetrics基本介紹

要說基線呢,我們先了解這個Paint.FontMetircs, 官方對該類的解釋是:Class that describes the various metrics for a font at a given text size., 意思是說,這玩意兒是繪制文本內容時存儲該文本內容位置信息的一個類。這個類中有如下五個字段:

(2) BaseLine 基線到底是啥?

上圖中這5個字段除了leading 外,其他四個都是相對于 基線BaseLine來確定的,那么,到底啥是基線??

先來看一張圖:

如上圖,標準的英文書寫是基于四線三格,其中,我們書寫英文的時候,都是以第三條線為基準,也就是說,基線就是這個四線三格中的第三條線!!

(3)Paint.FontMetrics中字段的含義及示意圖

官方文檔中對這幾個字段的解釋很簡單,但理解起來挺費勁,直接上圖,圖中的標注都是跑代碼之后確定的,如果有不準確的地方,歡迎指正:

根據上圖可知:

  • ascent

    文字內容的頂部到基線的距離。即 ascent=文字內容頂部Y坐標 - 基線Y坐標。由于android中坐標系是 右下為正,所以得到的ascent實際是一個負數。

  • descent

    文字內容的底部到基線的距離。即 descent=文字內容底部Y坐標 - 基線Y坐標。

  • 基線

    在圖中,基線的坐標用Y表示,在ImageSpan父類的 draw( ) 中,會傳入一個 float Y ,就是這個基線的坐標。實際上,基線的Y坐標=文字內容中間線Y坐標+1/2 (文字內容高度)

  • top

    對應圖中 文字所在行的top 坐標

  • bottom

    對應圖中 文字所在行的bottom 坐標

    需要注意:如果設置了行間距,且文本內容產生了換行,那么這個bottom 也會將行間距包裹。所以, 圖中藍色的文字內容中間線的Y軸坐標并不一定等于 (bottom+top)/2

4

自定義ImageSpan實現文字與圖片居中對齊

好了,前面說了那么多,終于進入正題了。。。

在上面的2 SpannableString+ImageSpan實現圖文混排中,我們已經知道官方并沒有給出文字與圖片居中對齊的模式,所以需要我們自定義。

關于自定義ImageSpan的分析,已經有前輩講解過了,此處不再贅述,請參考http://blog.csdn.net/gaoyucindy/article/details/39473135。

但是,按照該文章中的代碼實現的時候,有個問題就是:如果給TextView設置了行間距,且文本產生了換行,那么就無法對齊了!!

那么,設置了行間距之后,該如何實現文本和圖片的居中對齊呢?也有前輩分析過了,請看:http://www.cnblogs.com/withwind318/p/5541267.html, 但是,這篇文章中的實現方式沒有重寫 getSize( ) 方法,所以也有一個問題:文本和圖片并不是在TextView的居中位置,而且如果圖片高于文本的話,圖片會顯示不全!!如下圖:

參考了那么多了,終于該給出我的終極方案了!!

根據上面鏈接中兩位前輩的分析,其實我們自定義的時候,需要做的事情是 獲取文本內容的中間線以及圖片的中間線,然后獲取兩者差值,然后在draw方法中繪制圖片時將差值作為canvas.translate(x, transY) 中的transY;同時要重寫 getSize( )。

這樣最終實現的效果是,不論是否設置行間距,不論圖片大于文本還是文本大于圖片,都能實現文本和圖片的居中對齊!

看最終效果圖:

上代碼:

在Activity中使用:

xml布局文件:

上面的已經是完整代碼了,如果想直接下載運行,請到gitHub下載:https://github.com/CnPeng/CrazyAndroid

該倉庫中的b_01_spannableString_ImageSpan 對應該文中的內容

寫在最后,最近項目太緊了,過了年一直在加班。這次的總結也很倉促,本來想寫的更細一些,并且也想把SpannableString的使用完整總結,but 時間太緊了,先這樣吧,后面時間充足了再修正吧!

歡迎各位指正文中錯誤的地方,一起交流,一起進步!

參考鏈接:

  1. http://wangleyiang.iteye.com/blog/1771439

  2. http://blog.csdn.net/gaoyucindy/article/details/39473135

  3. http://www.cnblogs.com/withwind318/p/5541267.html

  4. http://stackoverflow.com/questions/27631736/meaning-of-top-ascentbaseline-descent-bottom-and-leading-in-androids-font

  5. https://github.com/GcsSloop/AndroidNote/blob/master/CustomView/Advance/%5B99%5DDrawText.md

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/286275.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/286275.shtml
英文地址,請注明出處:http://en.pswp.cn/news/286275.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于事件監聽機制的總結(Listener和Adapter)

記得以前看過事件監聽機制背后也是有一種設計模式的.(設計模式的名字記不清了,只記得背后實現的數據結構是數組.) 附上事件監聽機制的分析圖: 一個事件源可以承載多個事件(只要這個事件源支持這個事件就可以,男人就不支持生孩子的事件) 事件和監聽器有對應關系的. 下面用awt中…

【專升本計算機】專升本計算機期末考試復習題(C卷附答案)

文章目錄 一、單選題(每空2分,共20分)。二、填空題(每空2分,共30分)。三、程序題(每小題10分,共50分)一、單選題(每空2分,共20分)。 世界上第一臺電子計算機誕生于( B )年。 A.1956?? B.1946?? C.1944?? D.1940關閉正在運行的程序窗口,可以按( D )。 A.…

C語言試題二十五之編寫一個函數float function(double h),函數的功能使對變量h中的值保留2位小數,并對第三位進行四舍五入(規定h中的值位正數)。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 編寫一個函…

一、首頁、詳情頁、文章編輯頁制作《iVX低代碼/無代碼個人博客制作》

注:iVX也有免費直播課《第八期直播課》 一、首頁制作 首頁預覽如下: 首先在博客頁創建一個相對應項目: 接著選擇前臺,創建一個頁面,命名為首頁: 接著更改當前屏幕為小屏尺寸: 接著我們分…

HDU 4085 Steiner樹模板稱號

Dig The Wells Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 971 Accepted Submission(s): 416Problem DescriptionYou may all know the famous story “Three monks”. Recently they find some places ar…

Saga體系結構模式:微服務架構下跨服務事務的實現

在服務端應用程序中,我們往往會通過事務處理來保證數據一致性(Data Consistency),例如:當用戶從庫存中取走了一定數量的物品,這些物品會體現在用戶的提貨單上,與此同時,庫存中物品的…

Css樣式基礎

1.Css的語法 CSS的語法主要由兩個部分組成,一個是選擇器,一個是屬性、 選擇器又分為以下幾種: 1.元素選擇器:即Html標簽去掉括號的就是元素 2.類選擇器:所謂的類就是說class“名稱”,類的名稱是可以相同&am…

Android 清除png圖片的白色背景

/**清除背景顏色 * param mBitmap* param mColor 背景顏色值 eg:Color.WHITE** return*/ private static Bitmap getAlphaBitmap(Bitmap mBitmap, int mColor) {Bitmap mAlphaBitmap Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Confi…

【ArcGIS遇上Python】Python使用柵格數據

柵格數據是一個獨特的空間數據類型。很多地理處理工具都是為了處理柵格數據而開發的。 1. 列出柵格數據 ListRaster函數是以Python列表的形式返回工作控件中的柵格數據,該函數的語法格式是: ListRaster({wild_card},{raster_type}) 可選參數wild_card通過名稱限制返回的結果…

GPhone、OPhone、UPhone、APhone、IPhone:滿城盡帶XPhone

本文為原創,如需轉載,請注明作者和出處,謝謝! 最近一段時間智能手機市場是翻天覆地。各大廠商紛紛推出自己的手機操作系統和手機。Google、Apple、中國移動、中國聯通紛紛推出或即將推出自已 的智能手機操作系統(雖…

C語言試題二十六之請編寫一個函數function(char *s),該函數的功反轉字符串中的內容。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 請編寫一個…

二、文章發布頁制作及后臺實現《iVX低代碼/無代碼個人博客制作》

注:iVX也有免費直播課《第八期直播課》 一、文章編輯頁制作 當首頁制作完畢后,需要顯示內容就需要有文章數據,此時我們創建一個文章編輯頁增加對應的數據。 那么我們創建一個頁面,命名為文章發布頁: 接著我們查看標…

VS2013配置pro*C/C++開發環境

2019獨角獸企業重金招聘Python工程師標準>>> 1、軟件:VS2013,oracle10g 2、VS2013 新建VC空項目,然后在源文件中新建一個*.pc文件(不知道我的配置哪兒有問題,新建的pc文件必須和工程同名)&#…

查看linux版本的三種常用方法

1) 登錄到服務器執行 lsb_release -a ,即可列出所有版本信息,例如: [root3.5.5Biz-46 ~]# lsb_release -a LSB Version: 1.3 Distributor ID: RedHatEnterpriseAS Description: Red Hat Enterprise Linux AS release 4 (Nahant Update 1) Rel…

Windows 11 23H2 25131 推送!全新搜索體驗,優化應用商店

面向 Dev頻道的 Windows 預覽體驗成員,微軟現已推送 Windows 11 預覽版 Build 25131。主要變化1.微軟為 Windows 11 搜索引入全新體驗,當您在搜索結果中點擊“打開文件位置”時,現在將選擇文件資源管理器中的文件,此前只是打開文件…

C# RichTextBox 實現循環查找關鍵字

實現效果如上圖&#xff0c;點擊“Search”按鈕&#xff0c;開始從文首查找關鍵字“menu”&#xff0c;并高亮&#xff0c;再次點擊“Search”按鈕&#xff0c;繼續查找下一個。查找到文末&#xff0c;自動從文首重新查找。 private int _searchIndex 0;//查找開始位置/// <…

C語言試題二十七之請編寫程序,實現矩陣(3行3列)的轉置(即行列互換)。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 請編寫一個…

網站常見漏洞-- XSS攻擊

跨站攻擊&#xff0c;即Cross Site Script Execution(通常簡寫為XSS&#xff0c;因為CSS與層疊樣式表同名&#xff0c;故改為XSS) 是指攻擊者利用網站程序對用戶輸入過濾不足&#xff0c;輸入可以顯示在頁面上對其他用戶造成影響的HTML代碼&#xff0c;從而盜取用戶資料、利用用…

【ArcGIS遇上Python】從入門到精通系列之第一章:ArcGIS Python簡介

文章目錄1. Python簡介2. Python的特點3. ArcGIS的腳本語言4. ArcGIS中的Python腳本編輯器1. Python簡介 Python是一種跨平臺的計算機程序設計語言。 是一個高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言。最初被設計用于編寫自動化腳本(shell)&#xff0c;隨著版…

C# RichTextBox 做簡單的HTML代碼編輯器 ---------左側顯示行號

說明&#xff1a;此顯示行號為實際行號&#xff0c;不論是空行還是自動換行&#xff0c;都計算在內&#xff0c;跟實際IDE的行號不同&#xff0c;同步滾動會有半行高度以內的誤差。 實現原理&#xff0c;在RichTextBox 編輯器左側放置另一RichTextBox &#xff08;或其它控件也…