• android实现gif图与文字混排


      我们在进行qq聊天的时候发送表情,但这些表情都是并非静态的,很多其它的是动态图,gif图,那么怎样在androidclient显示动态gif图呢。

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

      因为我是截图,所以看不到动态效果。大家能够自己下载看一下。

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

      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<AnimatedImageSpan> localImageSpanRef = new WeakReference<AnimatedImageSpan>(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群:JRedu技术交流 (452379712)。与杰瑞教育高级project师在线互动

    作者:杰瑞教育
    出处:http://blog.csdn.net/jerehedu/ 
    本文版权归烟台杰瑞教育科技有限公司和CSDN共同拥有,欢迎转载,但未经作者允许必须保留此段声明。且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
  • 相关阅读:
    第三题 bfw在睡觉
    第二题 bfw和zhk的故事
    第一题 奶牛散步
    AC加油站7月比赛总结
    暑期机房联赛
    题解 P5663 【加工零件【民间数据】】
    题解 P1052 【过河】
    并发编程之进程
    网络编程socketserver
    网络编程之黏包
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6953180.html
Copyright © 2020-2023  润新知