日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android加载网络GIF完整解决方案

發(fā)布時(shí)間:2023/12/9 Android 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android加载网络GIF完整解决方案 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言:

加載并顯示gif是App常見(jiàn)的一個(gè)功能,像加載普通圖片一樣,大體應(yīng)該包含以下幾項(xiàng)功能:

1、自動(dòng)下載GIF到本地文件作為緩存,第二次加載同一個(gè)url的圖片不需要下載第二遍

2、由于GIF往往較大,要顯示圓形的進(jìn)度條提示下載進(jìn)度

3、在GIF完全下載完之前,先顯示GIF的第一幀圖像進(jìn)行占位,完全下載完畢之后自動(dòng)播放動(dòng)畫。

4、兩個(gè)不同的頁(yè)面加載同一張GIF,兩個(gè)頁(yè)面的加載進(jìn)度應(yīng)該一致

5、支持ViewPager同時(shí)加載多個(gè)GIF動(dòng)圖

效果演示:

實(shí)現(xiàn)思路:

1、關(guān)于下載和磁盤緩存:

我這里使用HttpConnection根據(jù)url進(jìn)行下載,在下載之前先將url字符串使用16位MD5進(jìn)行轉(zhuǎn)換,讓下載的文件名為url的MD5碼,然后以4096字節(jié)為單位,使用ByteStremBuffer進(jìn)行邊讀邊寫,防止下載過(guò)程中內(nèi)存溢出,而且不時(shí)的向磁盤寫入還可以幫助實(shí)現(xiàn)GIF第一幀占位的效果。

2、關(guān)于進(jìn)度指示:

我這里使用了一個(gè)圓形的第三方Progress Bar和一個(gè)TextView實(shí)現(xiàn),由于在下載過(guò)程中以4096為緩沖,所以每下載4096字節(jié)就會(huì)更新一次進(jìn)度UI。文件總大小由http返回報(bào)文的頭部的Content-length返回,通過(guò)已下載大小除以這個(gè)length得出下載百分比。

3、關(guān)于不同頁(yè)面的下載同步:

用戶在首頁(yè)會(huì)看到一個(gè)gif,這時(shí)候點(diǎn)擊圖片可以跳進(jìn)大圖頁(yè)繼續(xù)這個(gè)gif的下載,用戶在首頁(yè)的下載進(jìn)度到帶到大圖頁(yè)來(lái),不能讓用戶下載兩遍,也不能在大圖頁(yè)打開(kāi)一個(gè)才下載了一半的圖像。

首先在下載開(kāi)始之前,建立一個(gè)MD5.tmp的文件用來(lái)存儲(chǔ)下載內(nèi)容,在下載完畢之后將.tmp文件名后綴去掉,這樣通過(guò)文件系統(tǒng)檢索一個(gè)GIF是否已被下載的時(shí)候,沒(méi)有下載完成的圖片就不會(huì)被檢索出來(lái)。

如果有一個(gè)url已經(jīng)開(kāi)始了一次下載,這時(shí)候又有一個(gè)下載請(qǐng)求同一個(gè)url,此時(shí)會(huì)將請(qǐng)求的imageView,textView和progressBar使用一個(gè)WeakReference引用起來(lái),防止內(nèi)存泄漏,然后把這三個(gè)空間添加到一個(gè)HashMap里去,這個(gè)HashMap的key是url,value就是這些控件的弱引用組成的list。當(dāng)下載線程更新進(jìn)度或完成的時(shí)候,會(huì)從這個(gè)HashMap中根據(jù)url取出所有和這張gif有關(guān)的控件,然后把這些控件統(tǒng)一的更新?tīng)顟B(tài),這樣就可以保證不同頁(yè)面的控件的進(jìn)度相同,也避免了一個(gè)文件下載多次的情況。

4、關(guān)于使用GIF的第一幀進(jìn)行下載占位:

GIF的顯示使用了github上的開(kāi)源項(xiàng)目:android-gif-drawable,地址:https://github.com/koral--/android-gif-drawable。是一個(gè)非常優(yōu)秀的框架,其內(nèi)部使用c語(yǔ)言編寫了一些效率非常高的執(zhí)行代碼。

這個(gè)框架的可以直接根據(jù)輸入流進(jìn)行加載,也就是說(shuō)不用等gif文件完全下載完畢就可以顯示已經(jīng)下載完畢的內(nèi)容,甚至可以向?yàn)g覽器那樣一行像素一行像素的進(jìn)行加載,十分好用。

根據(jù)框架的這個(gè)特性,只需要將還沒(méi)有下載好的文件直接傳到Drawable里,讓道gifImageView中顯示即可,并且在這之前要判斷能否拿到第一幀,然后設(shè)置播放選項(xiàng)為暫停。

5、關(guān)于VIewPager的使用

在ViewPager的Adapter使用的時(shí)候遇到了很多麻煩,主要是由于ViewPager的緩存機(jī)制引起的,會(huì)引起顯示重復(fù),無(wú)控件顯示等等問(wèn)題,要解決在ViewPager中的使用,并讓GifImageView和普通ImageView一起在ViewPager中和平共處,需要先研究好ViewPager的緩存機(jī)制。在這里我是先根據(jù)所有圖片數(shù)量生成同等多的imageView放在一個(gè)數(shù)組里,然后ViewPager切換到哪張就從數(shù)組里拿出哪張放到ViewPager的Container里。GIfImageVIew也是這樣,不過(guò)是放在另一個(gè)數(shù)組里,根據(jù)position取得相應(yīng)的GIFImageView,然后用container來(lái)add,這里對(duì)于add過(guò)一遍的GIfImageView會(huì)報(bào)異常,通過(guò)catch解決。

?

具體代碼:

加載工具類:

?

import android.os.Handler; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest;import com.imaginato.qravedconsumer.task.AlxMultiTask; import com.lidroid.xutils.HttpUtils; import com.pnikosis.materialishprogress.ProgressWheel; import com.qraved.app.R;import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap;import pl.droidsonroids.gif.GifDrawable; import pl.droidsonroids.gif.GifImageView;/*** Created by Alex on 2016/6/16.*/ public class AlxGifHelper {public static class ProgressViews{public ProgressViews(WeakReference<gifimageview> gifImageViewWeakReference, WeakReference<progresswheel> progressWheelWeakReference, WeakReference<textview> textViewWeakReference,int displayWidth) {this.gifImageViewWeakReference = gifImageViewWeakReference;this.progressWheelWeakReference = progressWheelWeakReference;this.textViewWeakReference = textViewWeakReference;this.displayWidth = displayWidth;}public WeakReference<gifimageview> gifImageViewWeakReference;//gif顯示控件public WeakReference<progresswheel> progressWheelWeakReference;//用來(lái)裝飾的圓形進(jìn)度條public WeakReference<textview> textViewWeakReference;//用來(lái)顯示當(dāng)前進(jìn)度的文本框public int displayWidth;//imageView的控件寬度}public static ConcurrentHashMap<string,arraylist<progressviews>> memoryCache;//防止同一個(gè)gif文件建立多個(gè)下載線程,url和imageView是一對(duì)多的關(guān)系,如果一個(gè)imageView建立了一次下載,那么其他請(qǐng)求這個(gè)url的imageView不需要重新開(kāi)啟一次新的下載,這幾個(gè)imageView同時(shí)回調(diào)//為了防止內(nèi)存泄漏,這個(gè)一對(duì)多的關(guān)系均使用LRU緩存/*** 通過(guò)本地緩存或聯(lián)網(wǎng)加載一張GIF圖片* @param url* @param gifView*/public static void displayImage(final String url, GifImageView gifView, ProgressWheel progressBar , TextView tvProgress, int displayWidth){//首先查詢一下這個(gè)gif是否已被緩存String md5Url = getMd5(url);String path = gifView.getContext().getCacheDir().getAbsolutePath()+"/"+md5Url;//帶.tmp后綴的是沒(méi)有下載完成的,用于加載第一幀,不帶tmp后綴是下載完成的,//這樣做的目的是為了防止一個(gè)圖片正在下載的時(shí)候,另一個(gè)請(qǐng)求相同url的imageView使用未下載完畢的文件顯示一半圖像JLogUtils.i("AlexGIF","gif圖片的緩存路徑是"+path);final File cacheFile = new File(path);if(cacheFile.exists()){//如果本地已經(jīng)有了這個(gè)gif的緩存JLogUtils.i("AlexGIF","本圖片有緩存");if(displayImage(cacheFile,gifView,displayWidth)) {//如果本地緩存讀取失敗就重新聯(lián)網(wǎng)下載if (progressBar != null) progressBar.setVisibility(View.GONE);if (tvProgress!=null)tvProgress.setVisibility(View.GONE);return;}}//為了防止activity被finish了但是還有很多gif還沒(méi)有加載完成,導(dǎo)致activity沒(méi)有及時(shí)被內(nèi)存回收導(dǎo)致內(nèi)存泄漏,這里使用弱引用final WeakReference<gifimageview> imageViewWait= new WeakReference<gifimageview>(gifView);final WeakReference<progresswheel> progressBarWait= new WeakReference<progresswheel>(progressBar);final WeakReference<textview> textViewWait= new WeakReference<textview>(tvProgress);if(gifView.getId()!= R.id.gif_photo_view)gifView.setImageResource(R.drawable.qraved_bg_default);//設(shè)置沒(méi)有下載完成前的默認(rèn)圖片if(memoryCache!=null && memoryCache.get(url)!=null){//如果以前有別的imageView加載過(guò)JLogUtils.i("AlexGIF","以前有別的ImageView申請(qǐng)加載過(guò)該gif"+url);//可以借用以前的下載進(jìn)度,不需要新建一個(gè)下載線程了memoryCache.get(url).add(new ProgressViews(imageViewWait,progressBarWait,textViewWait,displayWidth));return;}if(memoryCache==null)memoryCache = new ConcurrentHashMap<>();if(memoryCache.get(url)==null)memoryCache.put(url,new ArrayList<progressviews>());//將現(xiàn)在申請(qǐng)加載的這個(gè)imageView放到緩存里,防止重復(fù)加載memoryCache.get(url).add(new ProgressViews(imageViewWait,progressBarWait,textViewWait,displayWidth));final HttpUtils http = new HttpUtils();// 下載圖片startDownLoad(url, new File(cacheFile.getAbsolutePath()+".tmp"), new DownLoadTask() {@Overridepublic void onStart() {JLogUtils.i("AlexGIF","下載GIF開(kāi)始");ProgressWheel progressBar = progressBarWait.get();TextView tvProgress = textViewWait.get();if(progressBar!=null){progressBar.setVisibility(View.VISIBLE);progressBar.setProgress(0);if(tvProgress==null)return;tvProgress.setVisibility(View.VISIBLE);tvProgress.setText("1%");}}@Overridepublic void onLoading(long total, long current) {int progress = 0;//得到要下載文件的大小,是通過(guò)http報(bào)文的header的Content-Length獲得的,如果獲取不到就是-1if(total>0)progress = (int)(current*100/total);JLogUtils.i("AlexGIF","下載gif的進(jìn)度是"+progress+"%"+" 現(xiàn)在大小"+current+" 總大小"+total);ArrayList<progressviews> viewses = memoryCache.get(url);if(viewses ==null)return;JLogUtils.i("AlexGIF","該gif的請(qǐng)求數(shù)量是"+viewses.size());for(ProgressViews vs : viewses){//遍歷所有的進(jìn)度條,修改同一個(gè)url請(qǐng)求的進(jìn)度顯示ProgressWheel progressBar = vs.progressWheelWeakReference.get();if(progressBar!=null){progressBar.setProgress((float)progress/100f);if(total==-1)progressBar.setProgress(20);//如果獲取不到大小,就讓進(jìn)度條一直轉(zhuǎn)}TextView tvProgress = vs.textViewWeakReference.get();if(tvProgress != null)tvProgress.setText(progress+"%");}//顯示第一幀直到全部下載完之后開(kāi)始動(dòng)畫getFirstPicOfGIF(new File(cacheFile.getAbsolutePath()+".tmp"),vs.gifImageViewWeakReference.get());}public void onSuccess(File file) {if(file==null)return;String path = file.getAbsolutePath();if(path==null || path.length()<5)return;File downloadFile = new File(path);File renameFile = new File(path.substring(0,path.length()-4));if(path.endsWith(".tmp"))downloadFile.renameTo(renameFile);//將.tmp后綴去掉Log.i("AlexGIF","下載GIf成功,文件路徑是"+path+" 重命名之后是"+renameFile.getAbsolutePath());if(memoryCache==null)return;ArrayList<progressviews> viewArr = memoryCache.get(url);if(viewArr==null || viewArr.size()==0)return;for(ProgressViews ws:viewArr){//遍歷所有的進(jìn)度條和imageView,同時(shí)修改所有請(qǐng)求同一個(gè)url的進(jìn)度//顯示imageViewGifImageView gifImageView = ws.gifImageViewWeakReference.get();if (gifImageView!=null)displayImage(renameFile,gifImageView,ws.displayWidth);//修改進(jìn)度條TextView tvProgress = ws.textViewWeakReference.get();ProgressWheel progressBar = ws.progressWheelWeakReference.get();if(progressBar!=null)progressBar.setVisibility(View.GONE);if(tvProgress!=null)tvProgress.setVisibility(View.GONE);}JLogUtils.i("AlexGIF",url+"的imageView已經(jīng)全部加載完畢,共有"+viewArr.size()+"個(gè)");memoryCache.remove(url);//這個(gè)url的全部關(guān)聯(lián)imageView都已經(jīng)顯示完畢,清除緩存記錄}@Overridepublic void onFailure(Throwable e) {Log.i("Alex","下載gif圖片出現(xiàn)異常",e);TextView tvProgress = textViewWait.get();ProgressWheel progressBar = progressBarWait.get();if(progressBar!=null)progressBar.setVisibility(View.GONE);if(tvProgress!=null)tvProgress.setText("image download failed");if(memoryCache!=null)memoryCache.remove(url);//下載失敗移除所有的弱引用}});}/*** 通過(guò)本地文件顯示GIF文件* @param localFile 本地的文件指針* @param gifImageView* displayWidth imageView控件的寬度,用于根據(jù)gif的實(shí)際高度重設(shè)控件的高度來(lái)保證完整顯示,傳0表示不縮放gif的大小,顯示原始尺寸*/public static boolean displayImage(File localFile,GifImageView gifImageView,int displayWidth){if(localFile==null || gifImageView==null)return false;JLogUtils.i("AlexGIF","準(zhǔn)備加載gif"+localFile.getAbsolutePath()+"顯示寬度為"+displayWidth);GifDrawable gifFrom;try {gifFrom = new GifDrawable(localFile);int raw_height = gifFrom.getIntrinsicHeight();int raw_width = gifFrom.getIntrinsicWidth();JLogUtils.i("AlexGIF","圖片原始height是"+raw_height+" 圖片原始寬是:"+raw_width);if(gifImageView.getScaleType() != ImageView.ScaleType.CENTER_CROP && gifImageView.getScaleType()!= ImageView.ScaleType.FIT_XY){//如果大小應(yīng)該自適應(yīng)的話進(jìn)入該方法(也就是wrap content),不然高度不會(huì)自動(dòng)變化if(raw_width<1 || raw_height<1)return false;int imageViewWidth = displayWidth;if(imageViewWidth < 1)imageViewWidth = raw_width;//當(dāng)傳來(lái)的控件寬度不大對(duì)的時(shí)候,就顯示gif的原始大小int imageViewHeight = imageViewWidth*raw_height/raw_width;JLogUtils.i("AlexGIF","縮放完的gif是"+imageViewWidth+" X "+imageViewHeight);ViewGroup.LayoutParams params = gifImageView.getLayoutParams();if(params!=null){params.height = imageViewHeight;params.width = imageViewWidth;}}else {JLogUtils.i("AlexGIF","按照固定大小進(jìn)行顯示");}gifImageView.setImageDrawable(gifFrom);return true;} catch (IOException e) {JLogUtils.i("AlexGIF","顯示gif出現(xiàn)異常",e);return false;}}/*** 用于獲取一個(gè)String的md5值* @param str* @return*/public static String getMd5(String str) {if(str==null || str.length()<1)return "no_image.gif";MessageDigest md5 = null;try {md5 = MessageDigest.getInstance("MD5");byte[] bs = md5.digest(str.getBytes());StringBuilder sb = new StringBuilder(40);for(byte x:bs) {if((x & 0xff)>>4 == 0) {sb.append("0").append(Integer.toHexString(x & 0xff));} else {sb.append(Integer.toHexString(x & 0xff));}}if(sb.length()<24)return sb.toString();return sb.toString().substring(8,24);//為了提高磁盤的查找文件速度,讓文件名為16位} catch (NoSuchAlgorithmException e) {JLogUtils.i("Alex","MD5加密失敗");return "no_image.gif";}}public static abstract class DownLoadTask{abstract void onStart();abstract void onLoading(long total, long current);abstract void onSuccess(File target);abstract void onFailure(Throwable e);boolean isCanceled;}/*** 開(kāi)啟下載任務(wù)到線程池里,防止多并發(fā)線程過(guò)多* @param uri* @param targetFile* @param task*/public static void startDownLoad(final String uri, final File targetFile, final DownLoadTask task){final Handler handler = new Handler();new AlxMultiTask<void,void,void>(){//開(kāi)啟一個(gè)多線程池,大小為cpu數(shù)量+1@Overrideprotected Void doInBackground(Void... params) {task.onStart();downloadToStream(uri,targetFile,task,handler);return null;}}.executeDependSDK();}/*** 通過(guò)httpconnection下載一個(gè)文件,使用普通的IO接口進(jìn)行讀寫* @param uri* @param targetFile* @param task* @return*/public static long downloadToStream(String uri, final File targetFile, final DownLoadTask task, Handler handler) {if (task == null || task.isCanceled) return -1;HttpURLConnection httpURLConnection = null;BufferedInputStream bis = null;OutputStream outputStream = null;long result = -1;long fileLen = 0;long currCount = 0;try {try {final URL url = new URL(uri);outputStream = new FileOutputStream(targetFile);httpURLConnection = (HttpURLConnection) url.openConnection();httpURLConnection.setConnectTimeout(20000);httpURLConnection.setReadTimeout(10000);final int responseCode = httpURLConnection.getResponseCode();if (HttpURLConnection.HTTP_OK == responseCode) {bis = new BufferedInputStream(httpURLConnection.getInputStream());result = httpURLConnection.getExpiration();result = result < System.currentTimeMillis() ? System.currentTimeMillis() + 40000 : result;fileLen = httpURLConnection.getContentLength();//這里通過(guò)http報(bào)文的header Content-Length來(lái)獲取gif的總大小,需要服務(wù)器提前把header寫好} else {Log.e("Alex","downloadToStream -> responseCode ==> " + responseCode);return -1;}} catch (final Exception ex) {handler.post(new Runnable() {@Overridepublic void run() {task.onFailure(ex);}});return -1;}if (task.isCanceled) return -1;byte[] buffer = new byte[4096];//每4k更新進(jìn)度一次int len = 0;BufferedOutputStream out = new BufferedOutputStream(outputStream);while ((len = bis.read(buffer)) != -1) {out.write(buffer, 0, len);currCount += len;if (task.isCanceled) return -1;final long finalFileLen = fileLen;final long finalCurrCount = currCount;handler.post(new Runnable() {@Overridepublic void run() {task.onLoading(finalFileLen, finalCurrCount);}});}out.flush();handler.post(new Runnable() {@Overridepublic void run() {task.onSuccess(targetFile);}});} catch (Throwable e) {result = -1;task.onFailure(e);} finally {if (bis != null) {try {bis.close();} catch (final Throwable e) {handler.post(new Runnable() {@Overridepublic void run() {task.onFailure(e);}});}}}return result;}/*** 加載gif的第一幀圖像,用于下載完成前占位* @param gifFile* @param imageView*/public static void getFirstPicOfGIF(File gifFile,GifImageView imageView){if(imageView==null)return;if(imageView.getTag(R.style.AppTheme) instanceof Integer)return;//之前已經(jīng)顯示過(guò)第一幀了,就不用再顯示了try {GifDrawable gifFromFile = new GifDrawable(gifFile);boolean canSeekForward = gifFromFile.canSeekForward();if(!canSeekForward)return;JLogUtils.i("AlexGIF","是否能顯示第一幀圖片"+canSeekForward);//下面是一些其他有用的信息 // int frames = gifFromFile.getNumberOfFrames(); // JLogUtils.i("AlexGIF","已經(jīng)下載完多少幀"+frames); // int bytecount = gifFromFile.getFrameByteCount(); // JLogUtils.i("AlexGIF","一幀至少多少字節(jié)"+bytecount); // long memoryCost = gifFromFile.getAllocationByteCount(); // JLogUtils.i("AlexGIF","內(nèi)存開(kāi)銷是"+memoryCost);gifFromFile.seekToFrame(0);gifFromFile.pause();//靜止在該幀imageView.setImageDrawable(gifFromFile);imageView.setTag(R.style.AppTheme,1);//標(biāo)記該imageView已經(jīng)顯示過(guò)第一幀了} catch (IOException e) {JLogUtils.i("AlexGIF","獲取gif信息出現(xiàn)異常",e);}} } </void,void,void></progressviews></progressviews></progressviews></textview></textview></progresswheel></progresswheel></gifimageview></gifimageview></string,arraylist<progressviews></textview></progresswheel></gifimageview></textview></progresswheel></gifimageview>

線程池:

android.os.AsyncTask; import android.os.Build;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** Created by Alex on 2016/4/19.* 用于替換系統(tǒng)自帶的AsynTask,使用自己的多線程池,執(zhí)行一些比較復(fù)雜的工作,比如select photos,這里用的是緩存線程池,也可以用和cpu數(shù)相等的定長(zhǎng)線程池以提高性能*/ public abstract class AlxMultiTask<params, result=""> extends AsyncTask<params, result=""> {private static ExecutorService photosThreadPool;//用于加載大圖的線程池private final int CPU_COUNT = Runtime.getRuntime().availableProcessors();private final int CORE_POOL_SIZE = CPU_COUNT + 1;public void executeDependSDK(Params...params){if(photosThreadPool==null)photosThreadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE);if(Build.VERSION.SDK_INT<11) super.execute(params);else super.executeOnExecutor(photosThreadPool,params);}} </params,></params,>

ViewPager Adpater的寫法(截取)

public class PhotoImageViewPageAdapter extends PagerAdapter {@Overridepublic Object instantiateItem(ViewGroup container, int position) {String imageUrl = "https://xxx.com/sdf/xxx.gif";JLogUtils.i("AlexGIF","當(dāng)前圖片->"+imageUrl);if(imageUrl.endsWith(".gif")){//如果是gif動(dòng)圖JLogUtils.i("AlexGIF","現(xiàn)在是gif大圖");View rl_gif = LayoutInflater.from(activity).inflate(R.layout.layout_photo_loading_gif_imageview, null);//這種方式容易導(dǎo)致內(nèi)存泄漏GifImageView gifImageView = (GifImageView) rl_gif.findViewById(R.id.gif_photo_view);ProgressWheel progressWheel = (ProgressWheel) rl_gif.findViewById(R.id.progress_wheel);CustomTextView tv_progress = (CustomTextView) rl_gif.findViewById(R.id.tv_progress);AlxGifHelper.displayImage(imageUrl,gifImageView,progressWheel,tv_progress,0);//最后一個(gè)參數(shù)傳0表示不縮放gif的大小,顯示原始尺寸try {container.addView(rl_gif);//這里要注意由于container是一個(gè)復(fù)用的控件,所以頻繁的addView會(huì)導(dǎo)致多張相同的圖片重疊,必須予以處置}catch (Exception e){JLogUtils.i("AlexGIF","父控件重復(fù)!!!!,這里出現(xiàn)異常很正常",e);}return rl_gif;//這里有個(gè)大坑,千萬(wàn)不能return container,但是在return之前必須addView}}return container;} }

布局文件

<!--?xml version="1.0" encoding="utf-8"?--> <relativelayout android:id="@+id/rl_gif" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="https://schemas.android.com/apk/res/android" xmlns:wheel="https://schemas.android.com/apk/res-auto"><pl.droidsonroids.gif.gifimageview android:id="@+id/gif_photo_view" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:layout_height="match_parent" android:layout_width="match_parent"><textview android:id="@+id/tv_progress" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="2%" android:textcolor="@color/white" android:textsize="15sp"><com.pnikosis.materialishprogress.progresswheel android:id="@+id/progress_wheel" android:layout_centerhorizontal="true" android:layout_centervertical="true" android:layout_gravity="center" android:layout_height="60dp" android:layout_width="60dp" wheel:matprog_barcolor="#5097DA" wheel:matprog_progressindeterminate="true"></com.pnikosis.materialishprogress.progresswheel></textview></pl.droidsonroids.gif.gifimageview></relativelayout>

中間的ProgressBar使用了一個(gè)第三方庫(kù)

dependencies {compile 'com.pnikosis:materialish-progress:1.7' }

?

總結(jié)

以上是生活随笔為你收集整理的Android加载网络GIF完整解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。