android實現gif圖與文字混排

來源:互聯網
上載者:User

標籤:

  我們在進行qq聊天的時候發送表情,但這些表情都是並不是靜態,更多的是動態圖,gif圖,那麼如何在android用戶端顯示動態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類,然後看一下傳入的值是否符合我們一開始寫好的RegexEMOTION_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),與傑瑞教育進階工程師線上互動

 

傑瑞教育
出處:http://blog.csdn.net/jerehedu/ 
本文著作權歸煙台傑瑞教育科技有限公司和CSDN共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文串連,否則保留追究法律責任的權利。 

android實現gif圖與文字混排

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.