Android SurfaceView 播放gif

Android SurfaceView 是Android系統(tǒng)中的高級(jí)組件飒房,它有自己的繪制界面赢织,可以在一個(gè)獨(dú)立的線程進(jìn)行UI的繪制擎鸠,因此不會(huì)阻塞主線程揭鳞,這也是我們使用SuefaceView播放gif圖片的原因炕贵。

先簡(jiǎn)單說一下思路,gif圖其實(shí)就是由一幀一幀的圖片組成野崇,當(dāng)我們想要播放gif的時(shí)候称开,其實(shí)就是播放gif的每一幀,這樣我們只需要解決以下就可以實(shí)現(xiàn)gif的播放:

1.gif一共有多少幀乓梨;

2.隨時(shí)間的推移尋找對(duì)應(yīng)的那一幀鳖轰;

3.播放該幀.

Android中有一個(gè)Moive類,這個(gè)類中提供的方法可以很好的解決這三個(gè)問題. movie.duration() 可以獲取一共有多少幀扶镀, movie.setTime()顯示哪一幀蕴侣。

代碼如下(有注釋):

public class GifSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder holder;
    private String path = "test.gif";
    private Movie movie;
    // 縮放系數(shù)
    private float zoom = 2;
    // 執(zhí)行 gif動(dòng)畫
    private Handler handler = new Handler();
    private Runnable runnable ;

    public GifSurfaceView(Context context) {
        super(context);
        initData();
    }

    public GifSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData();
    }

    public GifSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData();
    }

    private void initData() {
        runnable= new Runnable() {
            @Override
            public void run() {
                // gif動(dòng)畫 是由一幀 的圖片組成,實(shí)現(xiàn) gif動(dòng)畫就是將 一幀幀的圖 畫出來狈惫,
                // 首先獲取畫布
                Canvas canvas = holder.lockCanvas();
                // 保存當(dāng)前畫布狀態(tài)(此處保存畫布狀態(tài) 是為了保證 不影響下一幀的 縮放---下方 有 恢復(fù)狀態(tài))
                canvas.save();
                canvas.scale(zoom, zoom);
                //設(shè)置畫布
                movie.draw(canvas, 0, 0);
                //逐幀繪制圖片
                //這里使用時(shí)間戳 與總幀數(shù) 求余操作睛蛛,這樣 隨著時(shí)間的推移計(jì)算出該播放哪一幀
                movie.setTime((int) (System.currentTimeMillis() % movie.duration()));
                // 恢復(fù)之前保存的狀態(tài)
                canvas.restore();
                holder.unlockCanvasAndPost(canvas);
                // 循環(huán)執(zhí)行
                handler.postDelayed(runnable, 50);
            }
        };
        holder = getHolder();
        holder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }

    /**
     * 測(cè)量組件,設(shè)置 組件的寬高
     * 之所以 將Moive 的初始化放在這里是因?yàn)閟urfaceView再 默認(rèn)情況下是填充滿 父組件的
     * 設(shè)置SurfaceView的寬高 和gif寬高保持一致
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // surfaceView 默認(rèn)情況下 填充滿 父組件
        //加載gif圖片
        try {
            InputStream open = getContext().getAssets().open(path);
            // 使用影片對(duì)象 處理gif圖片
            movie = Movie.decodeStream(open);
            // 獲取 move對(duì)象的寬高(實(shí)際為gif 的寬高)
            int width = movie.width();
            int height = movie.height();
            // 設(shè)置surfaceView組件的寬高 使其保持 和 gif圖的寬高一致
            setMeasuredDimension((int) (width * zoom), (int) (height * zoom));
        } catch (IOException e) {
        }
    }

    public float getZoom() {
        return zoom;
    }

    public void setZoom(float zoom) {
        this.zoom = zoom;
    }

    // 開始執(zhí)行g(shù)if動(dòng)畫
    public void start() {
        handler.post(runnable);
    }

    // 開始執(zhí)行g(shù)if動(dòng)畫
    public void stop() {
        handler.removeCallbacks(runnable);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胧谈,一起剝皮案震驚了整個(gè)濱河市忆肾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菱肖,老刑警劉巖客冈,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異稳强,居然都是意外死亡场仲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門退疫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渠缕,“玉大人,你說我怎么就攤上這事褒繁∫嗔郏” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)燕差。 經(jīng)常有香客問我遭笋,道長(zhǎng),這世上最難降的妖魔是什么徒探? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任瓦呼,我火速辦了婚禮,結(jié)果婚禮上测暗,老公的妹妹穿的比我還像新娘央串。我一直安慰自己,他們只是感情好偷溺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布蹋辅。 她就那樣靜靜地躺著,像睡著了一般挫掏。 火紅的嫁衣襯著肌膚如雪侦另。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天尉共,我揣著相機(jī)與錄音褒傅,去河邊找鬼。 笑死袄友,一個(gè)胖子當(dāng)著我的面吹牛殿托,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剧蚣,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼支竹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了鸠按?” 一聲冷哼從身側(cè)響起礼搁,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎目尖,沒想到半個(gè)月后馒吴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瑟曲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年饮戳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洞拨。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扯罐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烦衣,到底是詐尸還是另有隱情篮赢,我是刑警寧澤齿椅,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布琉挖,位于F島的核電站启泣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏示辈。R本人自食惡果不足惜寥茫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望矾麻。 院中可真熱鬧纱耻,春花似錦、人聲如沸险耀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甩牺。三九已至蘑志,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贬派,已是汗流浹背急但。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搞乏,地道東北人波桩。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像请敦,于是被迫代替她去往敵國和親镐躲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354