首先还是先上截图
通过昨天的分析考虑到我们的edittext需要不断append表情或者文字,有些表情还需要从网络获取,通过分析我的思路是先给这个imagespan添加一个默认图占据他相应的位置然后再通过网络下载更换图片达到类似glide的placeHolder的效果,好了有了这个思路大家看一下我们是如何实现的。
代码如下
public class FullHeightSpan extends ImageSpan {
private int drawableHeight = 0;
private Paint.FontMetricsInt fm;
//跟网络下载有关没有网络处理的可自行忽略
private Drawable placeHolder;
private Drawable realDrawable;
private String url = "";
private boolean isURLLoad = false;
private boolean isLoading = false;
public FullHeightSpan(Drawable d) {
super(d);
}
public FullHeightSpan(Drawable d, String url) {
super(d);
isLoading = false;
isURLLoad = true;
placeHolder = d;
this.url = url;
}
public FullHeightSpan(Context context, Uri uri) {
super(context, uri);
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
if (fm != null) {
this.fm = fm;
drawableHeight = fm.descent - fm.ascent;
}
Drawable drawable = getResizedDrawable();
Rect bounds = drawable.getBounds();
return bounds.right;
}
@Override
public Drawable getDrawable() {
if (isURLLoad) { //判断是否为通过网络加载的处理
if (!isLoading) {//isLoading当开始下载为true防止多次下载重新进入方法1.下载失败 2.重新走构造方法(即重新下载)
isLoading = true;
OKHttpUtil.downLoadImage(url, new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
isLoading = false;
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
if (response.body() == null) return;
isLoading = true;
realDrawable = new GifDrawable(response.body().bytes());
}
});
}
if (realDrawable == null) {
return placeHolder;
} else {
return realDrawable;
}
} else {
return super.getDrawable();
}
}
private Drawable getResizedDrawable() {
Drawable d = getDrawable();
if (drawableHeight == 0) {
return d;
}
d.setBounds(new Rect(0, 0, (int) (1f * drawableHeight * d.getIntrinsicWidth() / d.getIntrinsicHeight()), drawableHeight));
return d;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
Drawable d = getResizedDrawable();
canvas.save();
int transY;
fm = paint.getFontMetricsInt();
transY = y + fm.ascent;
canvas.translate(x, transY);
d.draw(canvas);
canvas.restore();
}
}
还是以前的FullHeightSpan不同的是我们重写了getDrawable方法在添加标志如果是网络图下载的话走括号内的处理,否则返回默认super处理。
isLoading是为了防止重复下载让这个处理下载完了不在进处里,下载失败了重新下载,这里可能会有个问题(1.没有对下载失败次数控制即如果一直失败就停止下载,2.没有对网络校验)这个东西大家要用的话可以加个控制。
同时添加构造处理进构造方法重新置回默认状态。
这样的话就达到了我们在下载完图片之后替换原有的drawable了。(为了让大家看明白可能还有其他地方可以优化,大家如果要用的话可以自行优化)
最后就是在activity的调用了。
//从资源文件里面加载
Spannable spannable = getSpannable();
spEditText.append(spannable);
spEditText.setSelection(spEditText.getText().toString().length());
Toast.makeText(this, spEditText.getText().toString(), Toast.LENGTH_SHORT).show();
@NonNull
private Spannable getSpannable() throws IOException {
final GifDrawable placeHolder = new GifDrawable(getResources(), R.drawable.a);
final FullHeightSpan span = new FullHeightSpan(placeHolder, "http://ww2.sinaimg.cn/large/85cccab3gw1etduj2v0fbg20g009c1kx.jpg");
Spannable spannable = new SpannableString("sss");
spannable.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return spannable;
}
通过append方法将spannable添加到edittext中去,希望这个系列的文章能帮助大家更好的认识span,drawable。
github传送门点击这里