1. 程式人生 > >Android輕鬆實現播放Gif圖片

Android輕鬆實現播放Gif圖片

       Android的開發框架為我們的開發提供了不少很棒的控制元件,我們在開發的時候不需要太多的編碼就能輕鬆方便的使用這些控制元件,不過有些時候這些系統自帶的控制元件並不能夠完全滿足我們的需求。這時就需要我們發揮自己的想象力來實現我們特定需求的控制元件。

       今天為大家帶來一款可以展示Gif圖片的控制元件,實現播放Gif圖片的方法不止這一種,你也可以選擇其他的方式來實現(比如自己寫一個庫利用JNI呼叫或者直接用WebView來做展示),不過那就比較麻煩了,Android提供了可以展示類似這樣的檔案的方法,利用這些方法可以降低實現難度而且效果不會變差。

       展示圖片的過程實際上就是我們把圖片解碼到螢幕上的過程。Android為我們提供了一個叫做Movie的類可以幫我們實現解碼。這個控制元件不但可以用作展示Gif圖片也可以當做普通的ImageView控制元件來使用。下面我們通過程式碼來詳細解釋如何實現的

       首先看一下Demo的目錄結構

                                                    

       目錄結構非常簡單,主要用到的類就只有GIFView一個。下面貼出其中的程式碼為大家詳細解釋

package com.example.gifview;


import java.io.InputStream;
import java.lang.reflect.Field;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;


public class GifView extends ImageView {

	/**
	 * Movie物件用來解析gif圖片
	 */
	private Movie gifMovie;

	/**
	 * 開始時間,用來和當前時間比較,得出什麼時間播放gif
	 */
	private long mMovieStart;

	/**
	 * gif圖片的寬
	 */
	private int gifImageWidth;

	/**
	 * gif圖片的高
	 */
	private int gifImageHeight;

	
	/**
	 * 訪問attrs
	 */
	private AttributeSet attrs;

	/**
	 * 複寫GifView的構造方法
	 * 
	 * @param context
	 */
	public GifView(Context context) {
		super(context);
		
	}

	/**
	 * 複寫的GifView的構造方法
	 * 
	 * @param context
	 * @param attrs
	 */
	public GifView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.attrs = attrs;
		loadGifImage();
	}
	
	private void loadGifImage(){
		AttributeSet attrs = getContext().getResources().getXml(R.id.gifView);
		
		//生成一個TypedArray物件
		TypedArray array = getContext().obtainStyledAttributes(attrs,
				R.styleable.weatherView);
		
		//得到資源id
		int resourceId = getResourceId(array);
		
//檢查資源id
if(resourceId == -1){
	System.out.println("沒有獲取到圖片Id,請檢查是否在xml檔案裡設定了src屬性");
}

		// 以流的方式得到gif檔案
		InputStream is = getResources().openRawResource(resourceId);

		// 用Movie的decodeStream方法解碼檔案
		gifMovie = Movie.decodeStream(is);
		if (gifMovie != null) {
			Bitmap bitmap = BitmapFactory.decodeStream(is);
			gifImageWidth = bitmap.getWidth();
			gifImageHeight = bitmap.getHeight();
			bitmap.recycle();
		}
		
		
	}

	/**
	 *  複寫onDraw方法用於繪製View
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		if (gifMovie == null) {
			// 如果Movie為空說明不是一個gif影象,不是則呼叫父類方法,此時該控制元件等同於ImageView
			super.onDraw(canvas);
		} else {
			// 如果Movie不為空則說明是一個gif影象則展示gif影象
			showGifImage(canvas);
			// 重新整理
			invalidate();
		}
	}

	/**
	 *  複寫onMeasure方法,用來設定Gif寬高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if (gifMovie != null) {
			// 設定尺寸
			setMeasuredDimension(gifImageWidth, gifImageHeight);
		}
	}

	// 封裝的展示gif的方法
	private boolean showGifImage(Canvas canvas) {
		//得到系統時間
		long now = SystemClock.uptimeMillis();
		if (mMovieStart == 0) {
			// 把開始時間設定為當前時間
			mMovieStart = now;
		}
		int duration = gifMovie.duration();
		if (duration == 0) {
			// 如果沒有持續時間就設定為100
			duration = 100;
		}

		// 設定間隔時間
		int relTime = (int) ((now - mMovieStart) % duration);
		gifMovie.setTime(relTime);
		
		//在指定的位置進行繪製,這裡是左上角
		gifMovie.draw(canvas, 0, 0);
		if ((now - mMovieStart) >= duration) {
			mMovieStart = 0;
			return true;
		}
		return false;
	}

	/**
	 * 解析xml檔案裡的src傳來的引數,需要傳入一個TypeArray,Context,和引數陣列AttributeSet
	 * 
	 * @param array
	 * @param context
	 * @param attrs
	 * @return
	 */
	private int getResourceId(TypedArray array
			) {
		try {

			// 得到一個TypedArray裡的域
			Field field = TypedArray.class.getDeclaredField("mValue");

			// 設定可訪問性為true
			field.setAccessible(true);

			// 從類中取得域值
			TypedValue typeValueObject = (TypedValue) field.get(array);
			
			return typeValueObject.resourceId;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			array.recycle();
		}
		return -1;
	}
	
}


       我們先宣告一個Movie的物件,準備用來解析Gif圖片,然後我們需要一個變數來記錄開始播放的時間,用兩個整形變數來記錄需要播放的Gif圖片的寬高,最後我們實現播放Gif的基類是ImageView,相當於ImageView+Movie來實現的這個功能。需要順便一提的是,這裡用到一點關於Java反射的內容,為的是拿到配置檔案裡的Gif圖片ID。程式碼如下:

                //生成一個TypedArray物件
		TypedArray array = getContext().obtainStyledAttributes(attrs,
				R.styleable.weatherView);
		
		//得到資源id
		int resourceId = getResourceId(array);

        首先用loadImage()來載入Gif圖片,載入的時候需要得到圖片的寬高。

        自己實現控制元件除了繼承之外實現onMeasure和onDraw方法也是必要的。在onMeasure裡可以設定尺寸,同時可以判斷Movie物件是否為空,來決定這次展示是作為普通圖片還是Gif圖片來展示。

         在showGifImage方法裡就是實現展示Gif圖片的關鍵部分,這裡需要對Movie的duration屬性進行設定。用來控制播放週期。

       之後的過程就比較容易了,像普通的控制元件一樣來使用就可以了。下面是佈局檔案

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

	<com.example.gifview.GifView 
	    android:id="@+id/gifView"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:src="@drawable/weather_gif"/>
	
	<TextView 
	    android:id="@+id/textView1"
	    android:layout_below="@id/gifView"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:text="演示gif控制元件"/>
</RelativeLayout>

        這裡<com.example.gifview.GifView>就是我們需要的Gif控制元件。

        然後是在Activity裡設定佈局檔案


package com.example.gifview;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

順便需要提一下,在使用這個空間時可能需要設定硬體加速為false

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gifview"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:hardwareAccelerated="false" >
        <activity
            android:name="com.example.gifview.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


相關推薦

Android輕鬆實現播放Gif圖片

       Android的開發框架為我們的開發提供了不少很棒的控制元件,我們在開發的時候不需要太多的編碼就能輕鬆方便的使用這些控制元件,不過有些時候這些系統自帶的控制元件並不能夠完全滿足我們的需求。這時就需要我們發揮自己的想象力來實現我們特定需求的控制元件。     

Android ImageView播放gif圖片

當點選圖片的時候,gif圖片播放,當沒有點選的時候是gif的第一幀,這時是一張圖片。 參考:https://blog.csdn.net/guolin_blog/article/details/11100315 首先在values目錄下新建一個attrs.xml的檔案 &

Android簡單實現將手機圖片上傳到server中

sdk etc mov 創建 ast bmi 以及 lena ews 在本例中。將會簡單的實現安卓手機將圖片上傳到server中。本例使用到了 server端:PHP+APACHE 客戶端:JAVA 先簡單實現一下server端的上傳並測試上傳

Android ViewPager實現多個圖片水平滾動

oncreate iss block 如果 del ner ide extends 大小 1.示意圖 2.實現分析 (1).xml配置 <!-- 配置container和pager的clipChildre

Android 輕鬆實現 RecyclerView 懸浮條

SuspensionBar簡介:a RecyclerView suspension bar implementation like InstagramA RecyclerView suspension bar implementation like Instagram

Android 輕鬆實現語音識別

<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ />

Retrofit 2.0 超能實踐(三),輕鬆實現檔案/多圖片上傳/Json字串

通過前兩篇姿勢的入門 通過對Retrofit2.0的前兩篇的基礎入門和案例實踐,掌握了怎麼樣使用Retrofit訪問網路,加入自定義header,包括加入SSL證書,基本的除錯基礎,coolkie同步,但很多需求需要檔案的上傳,今天主題就來分享怎麼

Android輕鬆實現程式碼混淆

1、簡介 程式碼混淆(Obfuscated code)亦稱花指令,是將計算機程式的程式碼,轉換成一種功能上等價,但是難於閱讀和理解的形式的行為。 混淆的目的是為了加大反編譯的成本,但是並不能徹底防止反編譯。 2、如何開啟混淆 通常我們需要找到

unity 中播放GIF圖片

using System.Drawing;using System.Drawing.Imaging;using UnityEngine;using System.Collections;using System.Collections.Generic;public class AnimatedGifDrawe

Android實現非本地圖片的點選態

View adsView = inflater.inflate(R.layout.ads_item,null); ImageView img1 =(ImageView) adsView.findViewById(R.layout.ads_item_left); ImageView img2 =(ImageV

android學習——實現歡迎介面圖片動畫滑動切換

剛學習的時候想做兩個activity之間滑動切換的效果,就查了幾個部落格寫了之前的一篇“activity實現動畫切換”,現在看來這個功能好水,難看且基本不會有用到的。 但第一次啟動APP歡迎介面滑動進入的效果很常見,所以就查資料寫了這麼一個。 首先要了解一下ViewPa

Android輕鬆實現分享功能

在Android開發中,要實現分享功能,可能首先想到第三方的ShareSDK,其實,想要分享一些圖片,文字之類的完全沒必要在App中整合第三方SDK,利用原生的SDK就可以輕鬆實現分享功能。 Activity的跳轉方式   眾所周知,Activi

Android自定義Movie播放網路gif圖片

之前看到過一些帖子播放gif圖片的,大概看過兩種版本,一種是使用把gif解碼,分為一幀一幀的播放,另一種就是直接播放gif圖片。可以使用Movie類來播放,一種是使用框架,一個是android-gifview,另一個是android-gif-drawable,前者載入小的gif圖片沒問題

android中使用android-gif-drawable實現gif圖片解析出每幀圖片

hi,大家好:        好久沒有和大家見面了,因為各方面原因好久沒有更新blog,不過接下來我可能會有更多的時間來寫blog,希望可以給 大家帶來一些有用的知識點,可以幫助大家。 今天要介紹的是我們經常使用到的gif圖片的每幀解析,即給一個gif檔案,可以在andr

android Gif圖片播放

一、初始化: private void init() { movie = Movie.decodeStream(this.getResources().openRawResource(R.raw.test)); } 二、不斷的進行重新整理: @Override

Android開發本地及網路Mp3音樂播放器(五)實現專輯封面圖片

實現功能: 在MyMusicListFragment中實現專輯封面圖片 在item_music_list中實現專輯封面圖片 實現效果如圖: 實現程式碼如下: 在MediaUtiles中新增如下程式碼:/** * 獲取預設專輯圖片 */ pub

Android播放Gif動態圖片的幾種方式

下面介紹三種方式。 一、自定義GifView元件 簡介: 這個自定義的gifview元件核心程式碼就是讀取Gif資料,建立Movie例項,繪製每一幀圖片來達到Gif動態效果。這種方式比較直觀方便,程式碼量也少,不過經測試部分Gif圖片不能自適應大小,播放速度比實際播放速度快

android視訊播放截圖並製作成gif圖片

    導言:    根據文章標題,按三步走,一、視訊播放;二、連續截圖;三、轉換成gif。視訊播放很自然想到用MediaPlayer或者VideoView,但我在這裡踩了幾個坑,寫在這裡也希望別人少走點彎路。首先,是MediaPlayer+SurfaceView的坑,如果只

Android直播實現 Android端推流、播放

size input 準備 預覽 不必要 targe height 不出 oar 最近想實現一個Android直播,但是對於這方面的資料都比較零碎,一開始是打算用ffmpeg來實現編碼推流,在搜集資料期間,找到了幾個強大的開源庫,直接避免了jni的代碼,集成後只用少量的ja

Android app】DialogFragment上ViewPager+ RecyclerView實現多頁圖片list展示

效果圖:                                         &nb