当前位置: 首页 » 产品 » 出口外贸 » 正文

Android AutoWrapTextView中英文排版怎么解决

放大字体  缩小字体 发布日期: 2024-11-28 02:34   来源:http://www.baidu.com/  作者:无忧资讯  浏览次数:28
核心提示:  最近项目有新需求,UED给了个卡券密码的UI样式,如图:  我一看很简单啊,一个TextView解决问题,然后做好以后在模拟器里

  最近项目有新需求,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

 
 
[ 产品搜索 ]  [ 加入收藏 ]  [ 告诉好友 ]  [ 打印本文 ]  [ 违规举报 ]  [ 关闭窗口 ]

 

 
推荐图文
推荐产品
点击排行
    行业协会  备案信息  可信网站