span从入门到精通5 自定义ImageSpan适应edittext或者textView

本文介绍了一种使用自定义FullHeightSpan类实现EditText中表情或文字的动态加载和替换的方法。该方法允许在网络图片加载完成前显示占位图,并在图片加载完成后进行替换。

首先还是先上截图
表情测试
通过昨天的分析考虑到我们的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传送门点击这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值