用Glide很久了。除了对他膜拜就是膜拜,尤其是它可以实现gif的动态加载,那么我们今天就自己来实现以下如何动态的显示Gif。最后要提一句这个思路呢是从动脑学院得知的。他们是一个很牛逼的培训团体。希望广而告之
上图片
实现功能
- 1,加载本地gif
- 2,加载网络gif
用到技术
- 1,movie类
- 2,canvas类的绘制
- 3,网络下载
都是最简单的方法来实现逼格的效果
实现原理
gif就是一个无声的电影,你把电影的每一帧都会知道imageview上去就不分分钟了么
不就用到了canvas绘制一个gif大小的bigmap。然后在吧bitmap放到imageview里面去。
网络加载图片,就是查找本地是否有该gif,如果没有就先下载然后在从本地导入。
废话不多说直接上代码
package example.com.gifloader;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import example.com.gifloader.core.GifDecoder;
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
public static String url = "http://image.haha.mx/2014/02/02/middle/1115779_c221d1fc47b97bb1605cddc9c8aec0a7_1391347675.gif";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.iv);
try {
GifDecoder.with(this).load(url).into(imageView);
} catch (Exception e) {
e.printStackTrace();
}
}
}
和glide是不是很像就一句话 GifDecoder.with(this).load(url).into(imageView);
package example.com.gifloader.core;
import android.content.Context;
import android.net.Uri;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* Created by wanghao on 16/5/23.
* 加载gif
*/
public class GifDecoder {
public static Context context;
public static class Gif {
public static GifDecoder instance = new GifDecoder();
}
public static GifDecoder with(Context c) {
context = c;
return Gif.instance;
}
/**
* load gif file form inputstream
*/
public GifDrawer load(InputStream is) {
GifDrawer drawer = new GifDrawer();
drawer.setIs(is);
return drawer;
}
/**
* load gif file form uri
*/
public GifDrawer load(Uri uri) {
InputStream is = null;
try {
is = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return load(is);
}
/**
* load gif file form sdcard
*/
public GifDrawer load(File file) {
FileInputStream is = null;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return load(is);
}
/**
* load gif file form url
*/
public GifDrawer load(String url) {
String name = MD5Utils.string2MD5(url);
System.out.println(name);
FileInputStream is = null;
String path = context.getExternalCacheDir() + File.separator + name;
File file = new File(path);
if (file.exists()) {
try {
is = new FileInputStream(file);
return load(is);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
// 不存在 先下载下来
GifDrawer gifDrawer = new GifDrawer();
GifLoaderTask loadGifTask = new GifLoaderTask(gifDrawer, context);
loadGifTask.execute(url);
return gifDrawer;
}
return load(is);
}
}
package example.com.gifloader.core;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Handler;
import android.widget.ImageView;
import java.io.InputStream;
/**
* Created by wanghao on 16/5/23.
* gif的绘制
*/
public class GifDrawer {
private static final String TAG = "GifDrawer";
private InputStream is;
private ImageView imageView;
private Movie movie;
private Bitmap bitmap;
private Canvas canvas;
private Handler handler = new Handler();
private final long delayMills = 16;
private Runnable runnable = new Runnable() {
@Override
public void run() {
draw();
handler.postDelayed(runnable, delayMills);
}
};
private void draw() {
canvas.save();
movie.setTime((int) (System.currentTimeMillis() % movie.duration()));//这个是获取movie的某一帧,我们就不断地循环它
movie.draw(canvas, 0, 0);
imageView.setImageBitmap(bitmap);
canvas.restore();
}
/**
* 传递imagerview,将gif放到gif中去
*
* @param imageView
*/
public void into(ImageView imageView) {
this.imageView = imageView;
if (is == null) {
return;
} else if (imageView == null) {
throw new RuntimeException("imagetView can not be null");
} else {
// 开始在imageview里面绘制电影
movie = Movie.decodeStream(is);//gif小电影
if (movie == null) {
throw new IllegalArgumentException("Illegal gif file");
}
if (movie.width() <= 0 || movie.height() <= 0) {
return;
}
// 需要bitmap
bitmap = Bitmap.createBitmap(movie.width(), movie.height(), Bitmap.Config.RGB_565);
canvas = new Canvas(bitmap);
// 准备把canvas的小电影显示在imageview里面
handler.post(runnable);
}
}
public InputStream getIs() {
return is;
}
public void setIs(InputStream is) {
this.is = is;
}
public ImageView getImageView() {
return imageView;
}
public void setImageView(ImageView imageView) {
this.imageView = imageView;
}
}
package example.com.gifloader.core;
import android.content.Context;
import android.os.AsyncTask;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by wanghao on 16/5/23.
*/
class GifLoaderTask extends AsyncTask<String, Void, String> {
private final Context context;
private String name;
private GifDrawer gifDrawer;
public GifLoaderTask(GifDrawer gifDrawer, Context context) {
this.gifDrawer = gifDrawer;
this.context = context;
}
@Override
protected String doInBackground(String... params) {
try {
System.out.println(params[0]);
name = MD5Utils.string2MD5(params[0]);
System.out.println("--" + name);
InputStream is = HttpLoader.getInputStreanFormUrl(params[0]);
String path = context.getExternalCacheDir() + File.separator + name;
File file = new File(path);
FileOutputStream fops = new FileOutputStream(file);
int len = 0;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) != -1) {
fops.write(buffer, 0, len);
}
fops.close();
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return params[0];
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if (s != null) {
GifDecoder.with(context).load(s).into(gifDrawer.getImageView());
}
}
}
如果觉得async很low的可以用其他方法。反正现在下载方法很多。一个意思
代码在github上:https://github.com/wanghao200906/GifLoader
尊重原创:http://blog.csdn.net/wanghao200906/article/details/51483345