这是今年换工作的第一个需求,链接替换为标题
spanableString只有imagespan可以替换内容改为图片,但是不支持文字替换为文字或者图文文字
产品参考飞书都能做,搜索了一边,没找到好的方案,只能根据imagespan的原理,自己实现了一套方案出来,先贴代码把
/**
* 正则找出的link text 替换为 icon+title方案,目前支持单行显示
* 参考了.SpanUtils
*/
public class ImageTextSpan extends ReplacementSpan {
private MarkBlock markBlock;
@ColorInt
private int color;
private Drawable chatMsgLinkDrawable;
private EditText editText;
TextPaint textPaint = new TextPaint();
public ImageTextSpan(EditText editText, MarkBlock markBlock, @ColorInt int color, Drawable chatMsgLinkDrawable) {
//this.editText = editText;
this.markBlock = markBlock;
this.color = color;
//设置这个setBounds
chatMsgLinkDrawable.setBounds(0, 0, chatMsgLinkDrawable.getIntrinsicWidth(), chatMsgLinkDrawable.getIntrinsicHeight());
this.chatMsgLinkDrawable = chatMsgLinkDrawable;
}
/**
* @param paint
* @param text
* @param start
* @param end
* @param fontMetricsInt
* @return
*/
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fontMetricsInt) {
Drawable drawable = chatMsgLinkDrawable;
Rect rect = drawable.getBounds();
text = text.subSequence(start, end);
int width = -1;
if (markBlock.getUrlTitle() == null || markBlock.getUrlTitle().isEmpty()) {
width = (int) paint.measureText(text.toString()) + rect.right;
} else {
width = (int) paint.measureText(markBlock.getUrlTitle()) + rect.right;
}
if (fontMetricsInt != null) {
//mutilLine(paint, fontMetricsInt, width);
//单行居中显示
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int drHeight = rect.bottom - rect.top;
int centerY = fmPaint.ascent + fontHeight / 2;
fontMetricsInt.ascent = centerY - drHeight / 2;
fontMetricsInt.top = fontMetricsInt.ascent;
fontMetricsInt.bottom = centerY + drHeight / 2;
fontMetricsInt.descent = fontMetricsInt.bottom;
}
return width;
}
/***
* 多行,产品暂时看了飞书觉得不要,先不去调整这代码
* @param paint
* @param fontMetricsInt
* @param width
*/
private void sizeMoreLine(@NotNull Paint paint, Paint.@NotNull FontMetricsInt fontMetricsInt, int width) {
if (editText == null || editText.getMeasuredWidth() == 0) {
return;
}
//这里是为了改变高度问题
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
//java.lang.ArithmeticException: divide by zero
int i = width / (editText.getMeasuredWidth() != 0 ? editText.getMeasuredWidth() : width) + 1;//标识有多少行
int fontHeight = (fmPaint.descent - fmPaint.ascent) * i + sp2px(editText.getContext(), 2) * i;
// int drHeight = rect.bottom - rect.top;
int drHeight = fontHeight;
int centerY = fmPaint.ascent + fontHeight / 2;
fontMetricsInt.ascent = centerY - drHeight / 2;
fontMetricsInt.top = fontMetricsInt.ascent;
fontMetricsInt.bottom = centerY + drHeight / 2;
fontMetricsInt.descent = fontMetricsInt.bottom;
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
Drawable drawable = chatMsgLinkDrawable;
Rect rect = drawable.getBounds();
text = text.subSequence(start, end);
drawIcon(canvas, x, y, paint, drawable);
paint.setColor(color);
//drawMoreText(canvas, text, x, y, paint, rect);
drawText(canvas, text, x, y, paint, rect);
}
private void drawIcon(@NotNull Canvas canvas, float x, int y, @NotNull Paint paint, Drawable drawable) {
//这里画图片
canvas.save();
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int centerY = y + fmPaint.descent - fontHeight / 2;
int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
//这是多行居中代码,不过还有点bug
//int transY = drawMoreLine(y, drawable, width, fmPaint);
//居中
canvas.translate(x, transY);
drawable.draw(canvas);
canvas.restore();
}
private int drawMoreLine(int y, Drawable drawable, int width, Paint.FontMetricsInt fmPaint) {
if (editText == null || editText.getMeasuredWidth() == 0) {
return 0;
}
int i = width / editText.getWidth() + 1;//标识有多少行
int fontHeight = fmPaint.descent - fmPaint.ascent;
int centerY = y + fmPaint.descent - fontHeight / 2;
int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
return transY;
}
private void drawText(@NotNull Canvas canvas, CharSequence text, float x, int y, @NotNull Paint paint, Rect rect) {
if (markBlock.getUrlTitle() == null || markBlock.getUrlTitle().isEmpty()) {
canvas.drawText(text.toString(), x + rect.right, y, paint);
} else {
canvas.drawText(markBlock.getUrlTitle(), x + rect.right, y, paint);
}
}
private void drawMoreText(@NotNull Canvas canvas, CharSequence text, float x, int y, @NotNull Paint paint, Rect rect) {
//这里画文字
canvas.save();
//这里修改textPaint
textPaint.setTextSize(paint.getTextSize());
textPaint.setColor(color);
//平移对于位置
canvas.translate(x + rect.right, y);
StaticLayout staticLayout;
if (markBlock.getUrlTitle() == null || markBlock.getUrlTitle().isEmpty()) {
//canvas.drawText(text.toString(), x + rect.right, y, paint);
staticLayout = new StaticLayout(text.toString(), textPaint, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
} else {
//canvas.drawText(markBlock.getUrlTitle(), x + rect.right, y, paint);
staticLayout = new StaticLayout(markBlock.getUrlTitle(), textPaint, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
}
staticLayout.draw(canvas);
canvas.restore();
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
不方便发自己app,只能发下飞书输入框效果
在列表,就需要另外一个方案处理,还没处理完待续
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)