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

[导读]这篇文章主要给大家介绍了关于Android AutoWrapTextView中英文排版问题的解决方法

前言

最近项目有新需求,UED给了个卡券密码的UI样式,如图:

201752382334251.png?201742382345

我一看很简单啊,一个TextView解决问题,然后做好以后在模拟器里一看.....

5adf7948ef164a0e342aa4f2514cd9ae.png

纳尼,这个时候才想起来,TextView 中英文在一起会有排版问题,那怎么解决呢......

思路

刚开始的想法是一个字符一个字符的去绘制,绘制到最右边的临界点就换行绘制,结果实践以后发现不同的字符之间的间距不一样,显示会非常凌乱,又没有什么好的方案解决这个间距问题,所以这个方案pass;单个字符绘制不行那就一行一行绘制,根据View的长度把文本拆分成N行,然后一行一行的绘制。

实现

首先创建一个继承自View的AutoWrapTextViewpublic 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 

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 

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的宽高。

接下来就是绘制方法drawTextpublic void drawText(Canvas canvas) {

if (mSplitTextList == null || mSplitTextList.size() == 0) return;

int marginTop = getTopTextMarginTop();

for (int m = 0, length = mSplitTextList.size(); m 

String lineText = mSplitTextList.get(m);

canvas.drawText(lineText, mPaddingLeft, marginTop, mTextPaint);

marginTop += (mSplitTextRectArray[m].height() + mLineSpacingExtra);

}

}

首先得到第一行文本距离顶部的高度marginTop,然后循环文本绘制每一行文本内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值