您的位置:首页 > 理论基础 > 计算机网络

Android gif播放控件,支持网络图片,控件大小可控

2014-01-06 13:17 429 查看
第一次写博客就纠结在了这篇博客是不是原创的问题上,由于原来有人发过使用movie方式来播放Gif动画的例子,不过都非常简单,不支持网络gif动画的加载,而且,该控件的wrap_content属性根本没作用,我花了一些时间来把这些完成。

好,进入正题,我们通过android 系统提供的Movie类来辅助播放Gif,在Movie的声明上,该类提供了三个方法:

1.Movie.decodeByteArray(data, offset, length); 通过byte数据来进行初始化

2.Movie.decodeFile(pathName) 通过本地文件的路径来进行初始化

3.Movie.decodeStream(is) 通过流来进行初化

一开始,我使用Movie.decodeStream(is)来初始化资源文件下的gif文件并无问题,使用方法:movie = Movie.decodeStream(getResources().openRawResource(id));

但是在我使用一个URL打开一个流,将这个inputStrem传到Movie.decodeStream(is),这时候会出现一个异常,inputStrem reset,令我很是费解,打开Movie类里面的方法都是native声明的,也就是本地方法,看不到具体是怎么实现的,但是我觉得他肯定是不支持网络的流,具体情况还请懂的大神给我解惑一下。

于是我只要再多做一步,将inputStream又转换成了byte[],使用方法1来完成,通过测试,完成可以。代码如下:

public void setResource(final String urlstr) {
pools.execute(new Runnable() {
public void run() {
try {
URL url = new URL(urlstr);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.setRequestMethod("GET");
if (connection.getResponseCode() == 200) {
InputStream is = connection.getInputStream();

byte[] buffer = getByte(is);
handler.obtainMessage(1, buffer).sendToTarget();
} else {
Log.e("getResponseCode", connection.getResponseCode()
+ ":");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}


private final Handler handler = new Handler(this.getContext()
.getMainLooper()) {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
if(msg.obj==null){
return;
}
Log.e("look", "加载完毕!!!");
setResource((byte[]) msg.obj);
break;

default:
break;
}
}
};


@Override
protected void onDraw(Canvas canvas) {
long curTime = android.os.SystemClock.uptimeMillis();

// 第一次播放

if (movieStart == 0) {
movieStart = curTime;
}

if (movie != null) {
int duraction = movie.duration();

if (duraction == 0) {
duraction = 1000;
}

int relTime = (int) ((curTime - movieStart) % duraction);

movie.setTime(relTime);

movie.draw(canvas, 0, 0);

// 强制重绘
invalidate();
}

super.onDraw(canvas);
}


加载网络图片的功能有了,但是我又发现一个问题,由于我们重写的是View控件,没有重写onMeasure方法的时候,在控件测量的时候他是完全按照match_parent来处理的,所以在界面显示的时候看到的就是全部铺满到父控件里的,这样的效果显示是不我们想要的,于是我重写了onMeasure方法,具体代码如下

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e("look","onMeasure is called");

LayoutParams lp=(LayoutParams) getLayoutParams();
boolean isWidMat=lp.width==LayoutParams.MATCH_PARENT;
boolean isHeiMat=lp.height==LayoutParams.MATCH_PARENT;
boolean isWidWra=lp.width==LayoutParams.WRAP_CONTENT;
boolean isHeiWra=lp.height==LayoutParams.WRAP_CONTENT;
if(isWidMat&&isHeiMat){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}

if (movie != null) {
requestLayout();
setMeasuredDimension(isWidMat?MeasureSpec.getSize(widthMeasureSpec):isWidWra?movie.width():lp.width,
isHeiMat?MeasureSpec.getSize(heightMeasureSpec):isHeiWra?movie.height():lp.height);
} else {
setMeasuredDimension(isWidMat?MeasureSpec.getSize(widthMeasureSpec):isWidWra?0:lp.width,
isHeiMat?MeasureSpec.getSize(heightMeasureSpec):isHeiWra?0:lp.height);
}
}


这样,这个控件就算是拿得出来用了,如果有什么疑问,请留言,第一次写博客,请大家多多包涵。

源码下载地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android gif 网络