源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Android AutoWrapTextView中英文排版问题的解决方法

  • 时间:2021-09-25 01:50 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android AutoWrapTextView中英文排版问题的解决方法
[b]前言[/b] 最近项目有新需求,UED给了个卡券密码的UI样式,如图: [img]http://files.jb51.net/file_images/article/201705/201752382334251.png?201742382345[/img] 我一看很简单啊,一个TextView解决问题,然后做好以后在模拟器里一看..... [img]http://files.jb51.net/file_images/article/201705/201752382410446.png?201742382419[/img] 纳尼,这个时候才想起来,TextView 中英文在一起会有排版问题,那怎么解决呢...... [b]思路[/b] 刚开始的想法是一个字符一个字符的去绘制,绘制到最右边的临界点就换行绘制,结果实践以后发现不同的字符之间的间距不一样,显示会非常凌乱,又没有什么好的方案解决这个间距问题,所以这个方案pass;单个字符绘制不行那就一行一行绘制,根据View的长度把文本拆分成N行,然后一行一行的绘制。 [b]实现[/b] 首先创建一个继承自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,然后循环文本绘制每一行文本内容。 [b]效果图[/b] 我们来看下最后的效果 [img]http://files.jb51.net/file_images/article/201705/201752382607597.png?201742382619[/img] [b]结束语[/b] 至此整个类的逻辑分析就结束了,想看完整源码的可以移步:[url=https://github.com/chenpengfei88/AutoWrapTextView]https://github.com/chenpengfei88/AutoWrapTextView[/url]或者通过本地进行下载:[url=http://xiazai.jb51.net/201705/yuanma/AutoWrapTextView(jb51.net).rar]http://xiazai.jb51.net/201705/yuanma/AutoWrapTextView(jb51.net).rar[/url] 好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程素材网的支持。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部