久久96国产精品久久久-久久发布国产伦子伦精品-久久精品国产精品青草-久久天天躁夜夜躁狠狠85麻豆

技術員聯盟提供win764位系統下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當前位置:主頁 > 教程 > 服務器類 >

Android AutoWrapTextView中英文排版怎么解決

來源:技術員聯盟┆發布時間:2017-09-12 00:01┆點擊:

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

Android AutoWrapTextView中英文排版怎么解決 三聯

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

Android AutoWrapTextView中英文排版怎么解決

  納尼,這個時候才想起來,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,然后循環文本繪制每一行文本內容。

  效果圖

  我們來看下最后的效果

Android AutoWrapTextView中英文排版怎么解決

  結束語

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