在看某些直播时,会发现我们发送的聊天信息呈现的样式还是很利用空间的,此文做了相关界面的实现,截图如下:
Activity里实现主要涉及自定义Drawable和自定义DrawableSpan,并配合SpannableStringBuilder,代码如下:
TextView textView = findViewById(R.id.textView);
String userFlag = "VIP用户";
final String PLACEHOLDER = " ";
String flag = PLACEHOLDER + userFlag + PLACEHOLDER;
String username = "慕容:";
String content = "人若真能转世 世间若真有轮回" +
"那麽 我的爱 我们前世曾经是什麽\n" +
"你 若曾是江南采莲的女子\n" +
"我 必是你皓腕下错过的那朵\n" +
"你 若曾是逃学的顽童\n" +
"我 必是从你袋中掉下的那颗崭新的弹珠 ";
TextDrawable textDrawable = new TextDrawable(Color.BLUE, flag, Color.WHITE, textView.getTextSize());
SpannableStringBuilder builder = new SpannableStringBuilder(flag).append(username).append(content);
builder.setSpan(new TextDrawableSpan(textDrawable), 0, flag.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new ForegroundColorSpan(Color.GRAY), flag.length(),
flag.length() + username.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(builder);
TextDrawable代码如下:
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextPaint;
public class TextDrawable extends Drawable {
private Paint mBgPaint;
private TextPaint mTextPaint;
private String mText;
private RectF mRect;
public TextDrawable(@ColorInt int solidColor, String text, @ColorInt int textColor, float textSize) {
mText = text;
mRect = new RectF();
//初始化背景画笔
if (solidColor != 0) {
mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBgPaint.setColor(solidColor);
mBgPaint.setStyle(Paint.Style.FILL);
}
//初始化文字画笔
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(textColor);
mTextPaint.setTextSize(textSize);
mTextPaint.setStyle(Paint.Style.FILL);
//调整此drawable的边界,修改的值将存入getBounds里的矩阵里去
Rect rect = getBounds();
rect.set(0, 0, (int) mTextPaint.measureText(text),
mTextPaint.getFontMetricsInt().bottom - mTextPaint.getFontMetricsInt().top);
}
@Override
public void draw(@NonNull Canvas canvas) {
drawBg(canvas);
drawText(canvas);
}
/**
* draw背景
*/
private void drawBg(Canvas canvas) {
if (mBgPaint == null)
return;
//画圆角矩形作为背景图
Rect rect = getBounds();
mRect.set(rect);
float radius = (rect.bottom - rect.top) / 2;
canvas.drawRoundRect(mRect, radius, radius, mBgPaint);
}
/**
* draw文本
*/
private void drawText(Canvas canvas) {
Rect rect = getBounds();
Paint.FontMetrics metrics = new Paint.FontMetrics();
mTextPaint.getFontMetrics(metrics);
float textWidth = mTextPaint.measureText(mText);
float x = (rect.right - rect.left - textWidth) / 2;
float textHeight = metrics.bottom - metrics.top;
float y = (rect.bottom - rect.top - textHeight) / 2 - metrics.top;
//计算开始绘制x值,和基线baseline的y值,实现居中文本的效果
canvas.drawText(mText, x, y, mTextPaint);
}
@Override
public void setAlpha(int alpha) {
if (mBgPaint != null) {
mBgPaint.setAlpha(alpha);
}
mTextPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
if (mBgPaint != null) {
mBgPaint.setColorFilter(colorFilter);
}
mTextPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
//TRANSLUCENT表示只有绘制的地方才覆盖底下的内容
return PixelFormat.TRANSLUCENT;
}
}
TextDrawableSpan代码如下:
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.text.style.DynamicDrawableSpan;
/**
* 继承DynamicDrawableSpan是为了使默认居底部或基线的效果更改成居中的效果,主要是重写其draw方法
*/
public class TextDrawableSpan extends DynamicDrawableSpan {
private Drawable drawable;
public TextDrawableSpan(@NonNull Drawable drawable) {
this.drawable = drawable;
}
@Override
public Drawable getDrawable() {
return drawable;
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end,
float x, int top, int y, int bottom, @NonNull Paint paint) {
//注掉父类绘制的效果,居底部或位于基线
// super.draw(canvas, text, start, end, x, top, y, bottom, paint);
Drawable d = getDrawable();
canvas.save();
Rect bounds = d.getBounds();
//此为负数,表示向上移动整个canvas来实现居中效果
float dy = (bottom - bounds.bottom) * 0.5f;
canvas.translate(x, dy);
d.draw(canvas);
canvas.restore();
}
}