android gif 添加文字,android实现gif图与文字混排

我们在进行qq聊天的时候发送表情,但这些表情都是并不是静态的,更多的是动态图,gif图,那么如何在android客户端显示动态gif图呢。 在github上找到了这样一种方

我们在进行qq聊天的时候发送表情,,但这些表情都是并不是静态的,更多的是动态图,gif图,那么如何在android客户端显示动态gif图呢。

在github上找到了这样一种方法,Github地址https://github.com/TracyZhangLei/android-gif-demo

fcd72da84130c0acc1261bc860dd8cd9.png

由于我是截图,所以看不到动态效果,大家可以自己下载看一下。

我们首先来看一下该开源项目的代码。该开源项目主要是通过自定义一个Adapter-------chatAdapter,在ChatAdapter每一条的setText属性中使用了自定义的方法convertNormalStringToSpannableString

c33054e21f5b333560f8cefd7b2fc422.png

convertNormalStringToSpannableString方法的返回值是SpannableString

我们首先来了解一下什么是SpannableString

TextView通常用来显示普通文本,但是有时候需要对其中某些文本进行样式、事件方面的设置。Android系统通过SpannableString类来对指定文本进行相关处理,也就是说我们想要实现文字加动态表情的实现就要通过SpannableString这个类来实现。

private SpannableString convertNormalStringToSpannableString(String message , final TextView tv) {

SpannableString value = SpannableString.valueOf(message);

Matcher localMatcher = EMOTION_URL.matcher(value);

while (localMatcher.find()) {

String str2 = localMatcher.group(0);

int k = localMatcher.start();

int m = localMatcher.end();

if (m - k < 8) {

int face = fm.getFaceId(str2);

if(-1!=face){//wrapping with weakReference

WeakReference localImageSpanRef = new WeakReference(new AnimatedImageSpan(new AnimatedGifDrawable(cxt.getResources().openRawResource(face), new AnimatedGifDrawable.UpdateListener() {

@Override

public void update() {//update the textview

tv.postInvalidate();

}

})));

value.setSpan(localImageSpanRef.get(), k, m, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

}

}

}

return value;

}

首先将我们传入的message转化成SpannableString类,然后看一下传入的值是否符合我们一开始写好的正则表达式EMOTION_URL

private Pattern EMOTION_URL = Pattern.compile("\\[(\\S+?)\\]");

如果符合的话 我们取group(0)

附:group是针对()来说的,group(0)就是指的整个串,group(1)指的是第一个括号里的东西,group(2)指的第二个括号里的东西。

子表达式和起始位置和结束位置的差小于8,也就是符合我们的要求。调用FaceManager中的getFaceId方法

public int getFaceId(String faceStr){

if(mFaceMap.containsKey(faceStr)){

return mFaceMap.get(faceStr);

}

return -1;

}

找到我们用Map进行存储的表情

如果表情存在的话利用一个弱引用(WeakReference)把自定义的AnimatedImageSpan进行处理,使AnimatedImageSpan不那么的消耗内存,在UpdateListener中利用postInvalidate刷新界面。最后把SpannableString的setSpan方法,三个参数分别是要放进去的span ,起始位置,结束位置,flag标志。

关于flag:

Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, 这是在 setSpan 时需要指定的 flag,它是用来标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果。分别有 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)、 Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)、 Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)、

Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)。

最后将SpannableString返回,实现动态图文混排。

关于自定义的AnimatedImageSpan如下:

public class AnimatedImageSpan extends DynamicDrawableSpan {

private Drawable mDrawable;

public AnimatedImageSpan(Drawable d) {

super();

mDrawable = d;

// Use handler for 'ticks' to proceed to next frame

final Handler mHandler = new Handler();

mHandler.post(new Runnable() {

public void run() {

((AnimatedGifDrawable)mDrawable).nextFrame();

// Set next with a delay depending on the duration for this frame

mHandler.postDelayed(this, ((AnimatedGifDrawable)mDrawable).getFrameDuration());

}

});

}

@Override

public Drawable getDrawable() {

return ((AnimatedGifDrawable)mDrawable).getDrawable();

}

@Override

public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {

Drawable d = getDrawable();

Rect rect = d.getBounds();

if (fm != null) {

fm.ascent = -rect.bottom;

fm.descent = 0;

fm.top = fm.ascent;

fm.bottom = 0;

}

return rect.right;

}

@Override

public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {

Drawable b = getDrawable();

canvas.save();

int transY = bottom - b.getBounds().bottom;

if (mVerticalAlignment == ALIGN_BASELINE) {

transY -= paint.getFontMetricsInt().descent;

}

canvas.translate(x, transY);

b.draw(canvas);

canvas.restore();

}

}

如果大家有疑问,欢迎加入QQ群: (452379712),与杰瑞教育高级工程师在线互动

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值