EditText、ImageSpan和SpannableString的配合使用

本文介绍如何将文字转化为Bitmap并在EditText中显示,类似QQ聊天的@功能。通过处理使文字居中,并探讨了当文字过长导致的重复绘制问题,提到了StaticLayout作为可能的解决方案,但未能解决换行问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要功能是把文字转成Bitmap在editText显示,类似qq聊天输入‘@’关联好友功能

首先是把文字转成图片,下面做了一些处理以便文字居中显示

/**
 * 把文字转换成图片
 * @param context
* @param str
* @return
 */
public static Bitmap createBitmap(Context context,String str){
   int txtHeight = sp2px(context, 14)+1;
    Paint measurePaint = new Paint();
    measurePaint.setTextSize(txtHeight);
    int bmWidth = (int) measurePaint.measureText(str);//计算文字实际占用的宽度
    int bmHeight = 12+txtHeight;//将高度+10防止绘制椭圆时左右的文字超出椭圆范围
    Bitmap bm = Bitmap.createBitmap(bmWidth+20, bmHeight, Config.ARGB_8888);
    Canvas bmCanvas = new Canvas(bm);
    Paint bgPaint = new Paint();
    RectF targetRect = new RectF(5, 0, bmWidth+15, bmHeight);//矩形
    float roundPx = 5;
    bgPaint.setAntiAlias(true);//设置Paint为无锯齿
    bmCanvas.drawARGB(0, 0, 0, 0);// 透明色 
    bgPaint.setColor(context.getResources().getColor(R.color.bgColor_edittext_relation));//背景色
    bmCanvas.drawRoundRect(targetRect, roundPx, roundPx, bgPaint);//绘制圆角矩形
    Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    textPaint.setColor(context.getResources().getColor(R.color.item_main_textcolor));//字体颜色
    textPaint.setAntiAlias(true);
    textPaint.setStrokeWidth(2);
    textPaint.setTextSize(sp2px(context, 14));
    FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); 
    int baseline = (int) ((targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2);  
    // 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()  
    textPaint.setTextAlign(Paint.Align.CENTER);  
    bmCanvas.drawText(str, targetRect.centerX(), baseline, textPaint);
    bmCanvas.save(Canvas.ALL_SAVE_FLAG);
    bmCanvas.restore();
    return bm;
}
其中sp2px方法是把Android中的字体单位转成像素px
/** 
	 * 将sp值转换为px值,保证文字大小不变 
	 * @param spValue 
	 * @param fontScale 
	 * (DisplayMetrics类中属性scaledDensity) 
	 * @return 
	 */  
	public static int sp2px(Context context, float spValue) {  
	    final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;  
	    return (int) (spValue * fontScale + 0.5f);  
	}

其次是把bitmap显示在edittext中

private void insertEditText(String str) {
	    Bitmap bm = CommonUtils.createBitmap(context, str);
	    if (bm != null) {
	        ImageSpan imageSpan = new ImageSpan(context, bm);
	        SpannableString spannableString = new SpannableString( str );
	        spannableString.setSpan(imageSpan, 0,str.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
	        int index = edtContent.getSelectionStart();
	        Editable editable = edtContent.getEditableText();
	        if (index < 0 || index >= editable.length()) {
	            editable.append(spannableString);
	        } else {
	            editable.insert(editable.length(), spannableString);
	        }
	    }
	}

以上功能参考了网上的一些代码实现,具体网址不记得了。

这样比较适合文字较短的实现,当文字长度大于edittext的宽度时会出现重复绘制的现象,网上有人说用StaticLayout,它支持换行,我试了一下不行,不知道怎么解决这个bug。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值