国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android AutoWrapTextView中英文排版問題的解決方法

2019-10-23 18:28:10
字體:
來源:轉載
供稿:網友

前言

最近項目有新需求,UED給了個卡券密碼的UI樣式,如圖:

autowraptextview,android,中英文混排,中英文排序

我一看很簡單啊,一個TextView解決問題,然后做好以后在模擬器里一看.....

autowraptextview,android,中英文混排,中英文排序

納尼,這個時候才想起來,TextView 中英文在一起會有排版問題,那怎么解決呢......

思路

剛開始的想法是一個字符一個字符的去繪制,繪制到最右邊的臨界點就換行繪制,結果實踐以后發現不同的字符之間的間距不一樣,顯示會非常凌亂,又沒有什么好的方案解決這個間距問題,所以這個方案pass;單個字符繪制不行那就一行一行繪制,根據View的長度把文本拆分成N行,然后一行一行的繪制。

實現

首先創建一個繼承自View的AutoWrapTextView

public class AutoWrapTextView extends View {}

來看看它的構造方法

public AutoWrapTextView(Context context, AttributeSet attrs) {  super(context, attrs);  init(context, attrs);}private void init(Context context, AttributeSet attrs) {  initStyle(context, attrs);  initPaint();}

init方法里分別調用了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方法就是初始化一個文本畫筆

 private void initPaint() {  mTextPaint = new TextPaint();  mTextPaint.setAntiAlias(true);  mTextPaint.setTextSize(mTextSize);  mTextPaint.setColor(mTextColor);  mTextPaint.setTextAlign(Paint.Align.LEFT); }

接下來我們看看設置文本的方法setText方法

 public void setText(String text) {  if (TextUtils.isEmpty(text)) return;  //把文本轉換成Char數組  mTextCharArray = text.toCharArray();  requestLayout(); }

首先把文本轉換成Char數組,然后循環數組把整個文本拆分成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); }

首先創建一個屬性名為mSplitTextList的List集合用來存放拆分的文本;

mSingleTextWidth 為單行文本顯示的寬度;

currentSingleTextWidth 為當前一行累計計算的寬度;

然后開始循環Char數組,getSingleCharWidth方法就是計算單個Char的寬度;

如果currentSingleTextWidth 小于 mSingleTextWidth 就把Char添加到lineStringBuffer 當中,如果是最后一個Char就直接把lineStringBuffer添加到mSplitTextList集合當中

如果currentSingleTextWidth 大于 mSingleTextWidth,就把lineStringBuffer添加到mSplitTextList集合當中,重新給lineStringBuffer賦值,currentSingleTextWidth 歸0;

循環結束以后拆分好的文本就都添加到mSplitTextList集合當中了。

拆分完成以后循環mSplitTextList集合,得到每一行文本的Rect值,繪制文本的時候會用到,然后設置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,然后循環文本繪制每一行文本內容。

效果圖

我們來看下最后的效果

autowraptextview,android,中英文混排,中英文排序

結束語

至此整個類的邏輯分析就結束了,想看完整源碼的可以移步:https://github.com/chenpengfei88/AutoWrapTextView

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湖南省| 高台县| 高安市| 新乐市| 黄浦区| 桂东县| 荥阳市| 剑阁县| 紫阳县| 睢宁县| 电白县| 钟山县| 财经| 通榆县| 大悟县| 璧山县| 荣成市| 民权县| 绥滨县| 雅江县| 商丘市| 壤塘县| 买车| 宜黄县| 伊通| 依安县| 赣榆县| 华安县| 县级市| 孟村| 苏尼特左旗| 德保县| 乐清市| 大连市| 邢台市| 南漳县| 冀州市| 新乡市| 富源县| 邮箱| 柘城县|