最近在做一个小项目的时候遇到了这样的需求:用户需要发一个图文相关的EditText来编辑自己的文本。
可是我之前并没有接触过类似的需求。于是在我浏览了好几篇博文后发现,大多都需要去写一个自定义的EditText,但是其增添的内容无非是SpannableString和ImageSpan这两个类,况且我这个小项目需要的图片量以及所用到此文本类型的地方并不多,于是我就着重点放在了上述的两个类中。
而其用法则并不难,首先SpannableString(以下简称spString)的对象在实例化时,传入构造函数里的参数为一个修改过后的字符串,而这个字符串一般有特殊符作标识(以便解析时能识别)。因为我这里要插入图片,因此我用了html语言中的<img></img>标签。而ImageSpan在实例化时则需传入的参数为Context值以及uri资源文件,而我这里第二个参数传入的则是图片的Bitmap对象。
继而我们调用spString的setSpan(Object what, int start, int end, int flag)方法。
其中,第四个参数flag是相对于start和end参数而言的,它有四个值:
SPAN_INCLUSIVE_INCLUSIVE:前后都不包括。
SPAN_EXCLUSIVE_INCLUSIVE:前面包括,后面不包括。
SPAN_INCLUSIVE_EXCLUSIVE:前面不包括,后面包括。
SPAN_EXCLUSIVE_EXCLUSIVE:前后都包括。
这些参数一般都是对于如UrlSpan或者StyleSpan等类中的文字进行颜色调控时所调用会有不同,而我们这里只是插入图片,因此需要前后都包括进来,故选择第四个参数作为flag的传入值。紧接着我们需要去获取该EditText的光标点,继而决定我们如何插入该图片。而edit_text.getSelectionStart()方法则为我们提供了这样的需求。
故完整的调用代码如下:
private void insertImg(String path) {
//通过解析文件路径获取Bitmap对象
Bitmap imgBitmap = BitmapFactory.decodeFile(path);
//获取该屏幕的宽度
int width = getWindowManager().getDefaultDisplay().getWidth();
float scaleWidth = (float) width / imgBitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleWidth);
//设置图片的宽高
imgBitmap = Bitmap.createBitmap(imgBitmap, 0, 0, imgBitmap.getWidth(),
imgBitmap.getHeight(), matrix, true);
//获取特殊类型的对象
ImageSpan imgSpan = new ImageSpan(this, imgBitmap);
//用html标签符作为标识符
String tempUrl = "<img src=\"" + path + "\" />";
spStr = new SpannableString(tempUrl);
//将特殊类型的对象与SpannableString对象建立联系
spStr.setSpan(imgSpan, 0, tempUrl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//获取EditText的光标点
int index = etContent.getSelectionStart();
Editable et = etContent.getEditableText();
if (index < 0 || index >= et.length()) {
et.append(spStr);
} else {
et.insert(index, spStr);
}
//当插入图片后, 自动换行
et.insert(index + spStr.length(), " \n");
Log.i(TAG, etContent.getText().toString());
}
当我们打印时会发现,该图片已被封装成<img src="路径" />了,这时由于spString为我们解析了该字符串,就使得图片可以显示了。