您的位置:首页 > 其它

安卓TextView文本不满一行由于英文,标点符号等原因换行

2017-05-19 00:51 281 查看
1、

String aaa = “随便复制一段文字,用于测试,大家自己写下。有特殊符号,然后标点,英文什么的。”

2、

转半角函数,因为实际看起来半角函数比较好看

public static String ToDBC(String input) {
char[] c = input.toCharArray();
for (int i = 0; i< c.length; i++) {
if (c[i] == 12288) {
c[i] = (char) 32;
continue;
}if (c[i]> 65280&& c[i]< 65375)
c[i] = (char) (c[i] - 65248);
}
return new String(c);
}

3、

文本肯定是自定义控件,java文件见最下面,demo引自:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=555569&extra=page%3D1&page=1

4、

XXX.setText(ToDBC(aaa));

5、

上面3步骤的java文件

/**
* Project Name:TextViewDemo
* File Name:TypesetTextView.java
* Package Name:com.example.view
* Date:2014-11-29上午10:10:31
*/

package com.uzmap.pkg.utils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

/**
* ClassName:TypesetTextView
* Date:     2014-11-29 上午10:10:31
* @author Lenovo
* @version
* @since JDK 1.7
* @see
*/
public class TypesetTextView extends TextView {

private int mLineY;

private int mViewWidth;

public static final String TWO_CHINESE_BLANK = "  ";

private StringBuffer mText;
private StringBuffer newText = null;
private Paint mPaint;
/**VIEW的高度*/
private int mHeight = 0;
/**行高*/
private static final int LINE_HEIGHT = 40;
private int oneLine;//一行显示文字个数

private int number_of_words;//显示的字数

public TypesetTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
}

@Override
protected void onDraw(Canvas canvas) {

String text = getText().toString();// 获取文本内容
if (null == mText) {//以单例模式对文字进行拆分
mText = new StringBuffer(text);
TextPaint paint = getPaint();//获取画笔
paint.setColor(getCurrentTextColor());// 获取文字颜色将其设置到画笔上
paint.setTextSize(getTextSize());//设置文字大小
paint.setTypeface(getTypeface());//设置字体,包括字体的类型,粗细,还有倾斜、颜色等
paint.drawableState = getDrawableState();
mViewWidth = getMeasuredWidth();//获取填写字数的宽
mPaint = paint;
caculateChangeLine();//对文字进行分行处理
}
mLineY = getPaddingTop();//设置头部内边距
mLineY += getTextSize();
Layout layout = getLayout();//避免出现空视图

if (layout == null) {
return;
}
Paint.FontMetrics fm = mPaint.getFontMetrics();

int textHeight = (int) (Math.ceil(fm.descent - fm.ascent));
textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout
.getSpacingAdd());//获取文字的高度

String[] split = newText.toString().split("\n");//将分割好滴文字进行排版
if (null != split && split.length > 0) {//此处设置文本显示的高度,适配一些手机无法显示
int i = (split.length) + 0;//多设置了几行以避免显示不全(看情况进行修改)
int setheight = textHeight * i;
setHeight(setheight);//设置textview高度
}

for (int i = 0; i < split.length; i++) {
//此处为源例子上的写法,标点符号换行问题还是存在(楼主引用,ToDBC(aaa)的方法进行了修改,已解决这个bug)
//                layout.getLineCount()//获取显示的行数
//                int lineStart = layout.getLineStart(i);
//                int lineEnd = layout.getLineEnd(i);//获取每行要显示的字数
String string = split[i];
float width = StaticLayout.getDesiredWidth(string, 0,
string.length(), getPaint());

if (null == string || TextUtils.isEmpty(string)) {
continue;
}
int strWidth = (int) mPaint.measureText(string + "好好");//验证是否足够一个屏幕的宽度
if (needScale(string) && string.trim().length() > number_of_words - 5 && mViewWidth < strWidth)//判断是否足够一行显示的字数,足够久进行字的处理不够则直接画出来
//,避免出现字数不够,字间距被画出来的字间距过大影响排版
{// 判断是否结尾处需要换行,并且不是文本最后一行
drawScaledText(canvas, getPaddingLeft(), split[i], width, i);
} else {

canvas.drawText(split[i], getPaddingLeft(), mLineY, mPaint);// 将字符串直接画到控件上
}
mLineY += textHeight;
}

}

/**
* @Description:计算出一行显示的文字
*/
private String caculateOneLine(String str) {
//对一段没有\n的文字进行换行
String returnStr = "";
int strWidth = (int) mPaint.measureText(str);
int len = str.length();
int lineNum = strWidth / mViewWidth; //大概知道分多少行
int tempWidth = 0;
String lineStr;
int returnInt = 0;
if (lineNum == 0) {
returnStr = str;
mHeight += LINE_HEIGHT;
return returnStr;
} else {

oneLine = len / (lineNum + 1);    //一行大概有多少个字
if (number_of_words < oneLine) {
number_of_words = oneLine;
}

lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);

if (tempWidth < mViewWidth) //如果小了 找到大的那个
{
while (tempWidth < mViewWidth) {
oneLine++;
lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);
}
returnInt = oneLine - 1;
returnStr = lineStr.substring(0, lineStr.length() - 2);
} else//大于宽找到小的
{
while (tempWidth > mViewWidth) {
oneLine--;
lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);
}
returnStr = lineStr.substring(0, lineStr.length() - 1);
returnInt = oneLine;
}
mHeight += LINE_HEIGHT;
returnStr += "\n" + caculateOneLine(str.substring(returnInt - 1));
}
return returnStr;
}

public void caculateChangeLine() {
newText = new StringBuffer();
String tempStr[] = mText.toString().split("\n");
int len = tempStr.length;
for (int i = 0; i < len; i++) {
String caculateOneLine = caculateOneLine(tempStr[i]);
if (!TextUtils.isEmpty(caculateOneLine)) {
newText.append(caculateOneLine);
newText.append("\n");
}

}
this.setHeight(mHeight);
}

private void drawScaledText(Canvas canvas, int lineStart, String line,
float lineWidth, int currentline) {
float x = 0;
if (isFirstLineOfParagraph(lineStart, line)) {// 判断是否是第一行
canvas.drawText(TWO_CHINESE_BLANK, x, mLineY, getPaint());
float bw = StaticLayout.getDesiredWidth(TWO_CHINESE_BLANK, getPaint());
x += bw;

line = line.substring(3);
}
int gapCount = line.length() - 1;
int i = 0;
if (line.length() > 2 && line.charAt(0) == 12288
&& line.charAt(1) == 12288) {
String substring = line.substring(0, 2);
float cw = StaticLayout.getDesiredWidth(substring, getPaint());
canvas.drawText(substring, x, mLineY, getPaint());
x += cw;
i += 2;
}

float d = (mViewWidth - lineWidth) / gapCount;
for (; i < line.length(); i++) {
String c = String.valueOf(line.charAt(i));
float cw = StaticLayout.getDesiredWidth(c, getPaint());
canvas.drawText(c, x, mLineY, getPaint());
x += cw + d;
}
}

private boolean isFirstLineOfParagraph(int lineStart, String line) {
return line.length() > 3 && line.charAt(0) == ' '
&& line.charAt(1) == ' ';
}

private boolean needScale(String line) {// 判断是否需要换行
if (line == null || line.length() == 0) {
return false;
} else {
char charAt = line.charAt(line.length() - 1);
return charAt != '\n';
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: