Android AutoWrapTextView中英文排版問題的解決方法
前言
最近項(xiàng)目有新需求,UED給了個(gè)卡券密碼的UI樣式,如圖:
我一看很簡單啊,一個(gè)TextView解決問題,然后做好以后在模擬器里一看.....
納尼,這個(gè)時(shí)候才想起來,TextView 中英文在一起會(huì)有排版問題,那怎么解決呢......
思路
剛開始的想法是一個(gè)字符一個(gè)字符的去繪制,繪制到最右邊的臨界點(diǎn)就換行繪制,結(jié)果實(shí)踐以后發(fā)現(xiàn)不同的字符之間的間距不一樣,顯示會(huì)非常凌亂,又沒有什么好的方案解決這個(gè)間距問題,所以這個(gè)方案pass;單個(gè)字符繪制不行那就一行一行繪制,根據(jù)View的長度把文本拆分成N行,然后一行一行的繪制。
實(shí)現(xiàn)
首先創(chuàng)建一個(gè)繼承自View的AutoWrapTextView
public class AutoWrapTextView extends View { }
來看看它的構(gòu)造方法
public AutoWrapTextView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } private void init(Context context, AttributeSet attrs) { initStyle(context, attrs); initPaint(); }
init方法里分別調(diào)用了initStyle方法和initPaint方法;
initStyle方法主要解析自定義的屬性
private void initStyle(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoWrapTextViewStyle); mPaddingLeft = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingLeft, 0); mPaddingRight = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingRight, 0); mPaddingTop = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingTop, 0); mPaddingBottom = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_paddingBottom, 0); mTextColor = typedArray.getColor(R.styleable.AutoWrapTextViewStyle_textColor, Color.BLACK); mTextSize = typedArray.getDimensionPixelSize(R.styleable.AutoWrapTextViewStyle_textSize, 50); mLineSpacingExtra = typedArray.getInteger(R.styleable.AutoWrapTextViewStyle_lineSpacingExtra, 7); typedArray.recycle(); }
屬性名含義都很明顯不用過多解釋,initPaint方法就是初始化一個(gè)文本畫筆
private void initPaint() { mTextPaint = new TextPaint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(mTextColor); mTextPaint.setTextAlign(Paint.Align.LEFT); }
接下來我們看看設(shè)置文本的方法setText方法
public void setText(String text) { if (TextUtils.isEmpty(text)) return; //把文本轉(zhuǎn)換成Char數(shù)組 mTextCharArray = text.toCharArray(); requestLayout(); }
首先把文本轉(zhuǎn)換成Char數(shù)組,然后循環(huán)數(shù)組把整個(gè)文本拆分成N行文本,下面來看看核心方法splitText方法
private void splitText(int heightMode) { if (mTextCharArray == null) return; mSplitTextList = new ArrayList<>(); mSingleTextWidth = getMeasuredWidth() - mPaddingLeft - mPaddingRight; int currentSingleTextWidth = 0; StringBuffer lineStringBuffer = new StringBuffer(); for (int i = 0, length = mTextCharArray.length; i < length; i++) { char textChar = mTextCharArray[i]; currentSingleTextWidth += getSingleCharWidth(textChar); if (currentSingleTextWidth > mSingleTextWidth) { mSplitTextList.add(lineStringBuffer.toString()); lineStringBuffer = new StringBuffer(); currentSingleTextWidth = 0; i--; } else { lineStringBuffer.append(textChar); if (i == length - 1) mSplitTextList.add(lineStringBuffer.toString()); } } int textHeight = 0; mSplitTextRectArray = new Rect[mSplitTextList.size()]; for (int m = 0, length = mSplitTextList.size(); m < length; m++) { String lineText = mSplitTextList.get(m); Rect lineTextRect = new Rect(); mTextPaint.getTextBounds(lineText, 0, lineText.length(), lineTextRect); if (heightMode == MeasureSpec.AT_MOST) { textHeight += (lineTextRect.height() + mLineSpacingExtra); if (m == length - 1) { textHeight = textHeight + mPaddingBottom + mPaddingTop; } } else { if (textHeight == 0) textHeight = getMeasuredHeight(); } mSplitTextRectArray[m] = lineTextRect; } setMeasuredDimension(getMeasuredWidth(), textHeight); }
首先創(chuàng)建一個(gè)屬性名為mSplitTextList的List集合用來存放拆分的文本;
mSingleTextWidth 為單行文本顯示的寬度;
currentSingleTextWidth 為當(dāng)前一行累計(jì)計(jì)算的寬度;
然后開始循環(huán)Char數(shù)組,getSingleCharWidth方法就是計(jì)算單個(gè)Char的寬度;
如果currentSingleTextWidth 小于 mSingleTextWidth 就把Char添加到lineStringBuffer 當(dāng)中,如果是最后一個(gè)Char就直接把lineStringBuffer添加到mSplitTextList集合當(dāng)中
如果currentSingleTextWidth 大于 mSingleTextWidth,就把lineStringBuffer添加到mSplitTextList集合當(dāng)中,重新給lineStringBuffer賦值,currentSingleTextWidth 歸0;
循環(huán)結(jié)束以后拆分好的文本就都添加到mSplitTextList集合當(dāng)中了。
拆分完成以后循環(huán)mSplitTextList集合,得到每一行文本的Rect值,繪制文本的時(shí)候會(huì)用到,然后設(shè)置View的寬高。
接下來就是繪制方法drawText
public void drawText(Canvas canvas) { if (mSplitTextList == null || mSplitTextList.size() == 0) return; int marginTop = getTopTextMarginTop(); for (int m = 0, length = mSplitTextList.size(); m < length; m++) { String lineText = mSplitTextList.get(m); canvas.drawText(lineText, mPaddingLeft, marginTop, mTextPaint); marginTop += (mSplitTextRectArray[m].height() + mLineSpacingExtra); } }
首先得到第一行文本距離頂部的高度marginTop,然后循環(huán)文本繪制每一行文本內(nèi)容。
效果圖
我們來看下最后的效果
結(jié)束語
至此整個(gè)類的邏輯分析就結(jié)束了,想看完整源碼的可以移步:https://github.com/chenpengfei88/AutoWrapTextView或者通過本地進(jìn)行下載:http://xiazai.jb51.net/201705/yuanma/AutoWrapTextView(jb51.net).rar
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- Android用戶輸入自動(dòng)提示控件AutoCompleteTextView使用方法
- Android自動(dòng)獲取輸入短信驗(yàn)證碼庫AutoVerifyCode詳解
- Android中使用 AutoCompleteTextView 實(shí)現(xiàn)手機(jī)號格式化附帶清空歷史的操作
- Android自動(dòng)編輯文本框(AutoCompleteTextView)使用方法詳解
- Android中AutoCompleteTextView自動(dòng)提示
- Android仿新浪微博oauth2.0授權(quán)界面實(shí)現(xiàn)代碼(2)
- android中AutoCompleteTextView的簡單用法(實(shí)現(xiàn)搜索歷史)
- Android仿百度谷歌搜索自動(dòng)提示框AutoCompleteTextView簡單應(yīng)用示例
- 關(guān)于Android HTML5 audio autoplay無效問題的解決方案
- Android AutoCompleteTextView自動(dòng)提示文本框?qū)嵗a
- Android App開發(fā)的自動(dòng)化測試框架UI Automator使用教程
- Android中AutoCompleteTextView與TextWatcher結(jié)合小實(shí)例
- Android AutoValue使用和擴(kuò)展庫
相關(guān)文章
Android超詳細(xì)講解組件ScrollView的使用
本節(jié)帶來的是Android基本UI控件中的第十個(gè):ScrollView(滾動(dòng)條),或者我們應(yīng)該叫他?豎直滾動(dòng)條,對應(yīng)的另外一個(gè)水平方向上的滾動(dòng)條:HorizontalScrollView,先讓我們來了解ScrollView2022-03-03Android中TextView自動(dòng)識別url且實(shí)現(xiàn)點(diǎn)擊跳轉(zhuǎn)
這篇文章主要介紹了關(guān)于Android中TextView自動(dòng)識別url且實(shí)現(xiàn)點(diǎn)擊跳轉(zhuǎn)的相關(guān)資料,文中給出了詳細(xì)的示例代碼,對大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。2017-03-03Android實(shí)現(xiàn)Toast提示框圖文并存的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Toast提示框圖文并存的方法,實(shí)例分析了Toast提示框的參數(shù)設(shè)置及圖文調(diào)用的相關(guān)技巧,需要的朋友可以參考下2016-01-01Android編程之ListView和EditText發(fā)布帖子隱藏軟鍵盤功能詳解
這篇文章主要介紹了Android編程之ListView和EditText發(fā)布帖子隱藏軟鍵盤功能,結(jié)合實(shí)例形式分析了Android控件調(diào)用、隱藏軟鍵盤的原理與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-08-08Android中通過樣式來去除app的頭及界面全屏(備忘)的實(shí)現(xiàn)方法
這篇文章主要介紹了Android中通過樣式來去除app的頭及界面全屏(備忘)的相關(guān)資料,需要的朋友可以參考下2016-12-12android開發(fā)環(huán)境搭建詳解(eclipse + android sdk)
這篇文章主要介紹了android開發(fā)環(huán)境搭建詳解(eclipse + android sdk),需要的朋友可以參考下2014-05-05詳解Android中Service服務(wù)的基礎(chǔ)知識及編寫方法
這篇文章主要介紹了詳解Android中Service服務(wù)的基礎(chǔ)知識及編寫方法,包括Service的啟動(dòng)流程及生命周期等基本內(nèi)容,需要的朋友可以參考下2016-04-04