您的位置:首页 > 移动开发 > Android开发

自定义 TextView 两端对齐

2017-09-11 14:55 99 查看

TextView 两端对齐

Android上实现类似Word上那样两端对齐的样式,网上找了两个试了下挺不错的,AlignTextViewandroid-justifiedtextview。不过有点小问题, 有下面问题:

justifiedtextview显示一个url链接时会显示不完整

都不支持emoji表情

现在在 这个妹子文章 的基础上修改一下,这个和justifiedtextview一样,写的还是挺明了的。

1、链接显示不完整,在draw中mViewWidth的长度减少点,我这里减了5

2、遇到emoji表情,读两个字符就好了

自定义TextView用在列表中可能是会卡顿的,不过我这个是用在后台生成图片的,所以并没有卡顿这一说,大家平时用的时候注意,下面是全部代码:

public class JustifyTextView extends TextView {

private int mLineY = 0;//总行高
private int mViewWidth;//TextView的总宽度
private TextPaint paint;

public JustifyTextView(Context context) {
super(context);
init();
}

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

public JustifyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
paint = getPaint();
paint.setColor(getCurrentTextColor());
paint.drawableState = getDrawableState();
}

@Override
protected void onDraw(Canvas canvas) {
mViewWidth = getMeasuredWidth() - 5;//获取textview的实际宽度
mLineY += getTextSize();

String text = getText().toString();

Layout layout = getLayout();
int lineCount = layout.getLineCount();
for (int i = 0; i < lineCount; i++) {//每行循环
int lineStart = layout.getLineStart(i);
int lineEnd = layout.getLineEnd(i);
String lineText = text.substring(lineStart, lineEnd);//获取TextView每行中的内容
if (needScale(lineText)) {
if (i == lineCount - 1) {//最后一行不需要重绘
canvas.drawText(lineText, 0, mLineY, paint);
} else {
float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, paint);
drawScaleText(canvas, lineText, width);
}
} else {
canvas.drawText(lineText, 0, mLineY, paint);
}
mLineY += getLineHeight();//写完一行以后,高度增加一行的高度
}
}

/**
* 重绘此行.
*
* @param canvas    画布
* @param lineText  该行所有的文字
* @param lineWidth 该行每个文字的宽度的总和
*/
private void drawScaleText(Canvas canvas, String lineText, float lineWidth) {
float x = 0;
if (isFirstLineOfParagraph(lineText)) {
String blanks = "  ";
canvas.drawText(blanks, x, mLineY, paint);
float width = StaticLayout.getDesiredWidth(blanks, paint);
x += width;
lineText = lineText.substring(3);
}
//比如说一共有5个字,中间有4个间隔,
//那就用整个TextView的宽度 - 5个字的宽度,
//然后除以4,填补到这4个空隙中
float interval = (mViewWidth - lineWidth) / (lineText.length() - 1);
for (int i = 0; i < lineText.length(); ) {
String character;
if (!isEmojiCharacter(lineText.charAt(i))) {
// 是emoji表情
character = String.valueOf(lineText.substring(i, i += 2));
} else {
character = String.valueOf(lineText.charAt(i++));
}
float cw = StaticLayout.getDesiredWidth(character, paint);
canvas.drawText(character, x, mLineY, paint);
x += (cw + interval);
}
}

/**
* 判断是不是段落的第一行.
* 一个汉字相当于一个字符,此处判断是否为第一行的依据是:
* 字符长度大于3且前两个字符为空格
*
* @param lineText 该行所有的文字
*/
private boolean isFirstLineOfParagraph(String lineText) {
return lineText.length() > 3 && lineText.charAt(0) == ' ' && lineText.charAt(1) == ' ';
}

/**
* 判断需不需要缩放.
*
* @param lineText 该行所有的文字
* @return true 该行最后一个字符不是换行符  false 该行最后一个字符是换行符
*/
private boolean needScale(String lineText) {
if (lineText.length() == 0) {
return false;
} else {
return lineText.charAt(lineText.length() - 1) != '\n';
}
}

/**
* 判断是否是Emoji
*
* @param codePoint 比较的单个字符
* @return
*/
private boolean isEmojiCharacter(char codePoint) {
return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) ||
(codePoint == 0xD) || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) || ((codePoint >= 0x10000)
&& (codePoint <= 0x10FFFF));
}

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