Android中实现gif动画
一、需求
Android本身没有提供直接显示gif动画的相关控件,因此需要自定义GifImageView类来实现gif的播放,主要是使用的Movie类来解决的。
二、自定义GifImageView
public class GifImageView extends AppCompatImageView {
private static final String TAG = "ImageView";
private static final int DEFAULT_MOVIE_DURATION = 2000;
private Movie mMovie;
private long mMovieStart;
private int mCurrentAnimationTime; /**
* Scaling factor to fit the animation within view bounds.
*/
private float mScale = 1;
private boolean mVisible = true; public GifImageView(Context context) {
this(context, null);
} public GifImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public GifImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setViewAttributes();
} @SuppressLint("NewApi")
public void setViewAttributes() {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mMovie != null) {
updateAnimationTime();
drawMovieFrame(canvas);
invalidateView();
}
} /**
* Draw current GIF frame
*/
private void drawMovieFrame(Canvas canvas) {
mMovie.setTime(mCurrentAnimationTime);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(mScale, mScale);
mMovie.draw(canvas, 0, 0);
canvas.restore();
} /**
* Calculate current animation time
*/
private void updateAnimationTime() {
long now = android.os.SystemClock.uptimeMillis(); if (mMovieStart == 0) {
mMovieStart = now;
} int dur = mMovie.duration(); if (dur == 0) {
dur = DEFAULT_MOVIE_DURATION;
} mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
} /**
* Invalidates view only if it is visible.
*/
@SuppressLint("NewApi")
private void invalidateView() {
if (mVisible) {
postInvalidateOnAnimation();
}
} @SuppressLint("NewApi")
@Override
public void onScreenStateChanged(int screenState) {
super.onScreenStateChanged(screenState);
mVisible = screenState == SCREEN_STATE_ON;
invalidateView();
} @SuppressLint("NewApi")
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mVisible = visibility == View.VISIBLE;
invalidateView();
} @Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
mVisible = visibility == View.VISIBLE;
invalidateView();
} public void setMovieResource(int movieResId) {
mMovie = Movie.decodeStream(getResources().openRawResource(movieResId));
requestLayout();
} @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed && mMovie != null) {
float scaleW = (float) getWidth() / mMovie.width();
float scaleH = (float) getHeight() / mMovie.height();
mScale = Math.min(scaleH, scaleW);
}
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mMovie != null) {
int mMeasureWidth;
int mMeasureHeight;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.AT_MOST) {
Log.e(TAG, "---moviewidth before" + mMovie.width());
int movieWidth = mMovie.width();
mMeasureWidth = Math.min(movieWidth, widthSize);
Log.e(TAG, "---moviewidth after" + mMovie.width());
} else {
mMeasureWidth = widthSize;
}
if (heightMode == MeasureSpec.AT_MOST) {
Log.e(TAG, "---height " + mMovie.height());
int movieHieght = mMovie.height();
mMeasureHeight = Math.min(movieHieght, heightSize); } else {
mMeasureHeight = heightSize;
}
Log.e(TAG, "--wi : " + mMeasureWidth + " h : " + mMeasureHeight);
setMeasuredDimension(mMeasureWidth, mMeasureHeight);
}
}
}
三、layout中添加控件
<com.pax.view.GifImageView
android:id="@+id/gif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/space_horizontal"
android:layout_gravity="center"
android:visibility="invisible"/>
四、activity中实现
直接调用set方法,将gif资源传给gifview即可。
例如:
@Bind(R.id.gif)
GifImageView gif;
gif.setMovieResource(R.drawable.gif_searching);
Android中实现gif动画的更多相关文章
- android中设置Animation 动画效果
在 Android 中, Animation 动画效果的实现可以通过两种方式进行实现,一种是 tweened animation 渐变动画,另一种是 frame by frame animation ...
- Android(java)学习笔记199:Android中补间动画(Tween Animation)
本文主要简单介绍补间动画使用代码实现, 关于使用xml实现补间动画,可以参看:自定义控件三部曲之动画篇(一)——alpha.scale.translate.rotate.set的xml属性及用法 1. ...
- 在Android中显示GIF动画
gif图动画在android中还是比较常用的,比如像新浪微博中,有很多gif图片,而且展示非常好,所以我也想弄一个.经过我多方的搜索资料和整理,终于弄出来了,其实github上有很多开源的gif的展示 ...
- 【转】[置顶] 在Android中显示GIF动画
gif图动画在Android中还是比较常用的,比如像新浪微博中,有很多gif图片,而且展示非常好,所以我也想弄一个.经过我多方的搜索资料和整理,终于弄出来了,其实github上有很多开源的gif的展示 ...
- Android(java)学习笔记142:Android中补间动画(Tween Animation)
本文主要简单介绍补间动画使用代码实现, 关于使用xml实现补间动画, 可以参看:自定义控件三部曲之动画篇(一)——alpha.scale.translate.rotate.set的xml属性及用法 1 ...
- Android中的帧动画与补间动画的使用
前言 在日常开发中,我们有时候须要一些好看的动画效果,这时能够充分利用Android提供的这几种动画来实现. Android提供了3种类型的动画: 补间动画:补间动画能够应用于View,让你能够定义一 ...
- Android中的布局动画
简介 布局动画是给布局的动画,会影响到布局中子对象 使用方法 给布局添加动画效果: 先找到要设置的layout的id,然后创建布局动画,创建一个LayoutAnimationController,并把 ...
- Android中使用抖动动画吸引来用户注意
原文:http://www.androidcn.org/topic/552e65bc61d460226ab27a5c 在应用中,有时候我们要吸引用户去点击某些按钮,比如应用市场的推荐按钮,为了能够吸引 ...
- Android 中如何使用动画
1:首先在res/anim/文件夹下建立动画xml文件. 2:在java代码中对UI控件使用动画. //加载动画 Animation myAnim=AnimationUtils.loadAnimati ...
随机推荐
- win7旗舰版64位GHOST版的,安装telnet客户端时,提示:出现错误。并非所有的功能被成功更改。
win7旗舰版64位GHOST版的,安装telnet客户端时,提示:出现错误.并非所有的功能被成功更改. 从安装成功的电脑上拷贝ghost版本缺少的文件,然后再安装telnet客户端,我已打包 链接: ...
- VS2017用正则表达式替换多行代码
await IndexManyAsync\(item.Value, item.Key, "doc"\);\r\n.*\}.*\r\n.*\} 上面的代码,匹配的是下面的代码 awa ...
- GOF23设计模式
单例设计模式 饿汉式:
- Struts2各个功能详解(2)-输入校验和拦截器
前面知道了struts2的架构图和struts2的自动封装表单参数和数据类型自动转换,今天来学struts2的第三第四个东西,输入校验和拦截器. 一:输入校验 客户端校验进行基本校验,如检验非空字段 ...
- nginx访问502 gateway,*1 connect() failed (111: Connection refused) while connecting to upstream
安装好nginx,php环境后,配置虚拟主机,结果访问后就报502 gateway,查看日志文件后,显示错误如下: 2019/04/29 16:24:39 [error] 19433#19433: * ...
- MySQL数据库(增删改查语句)
MySQL数据库(增删改查语句)一.登录数据库:----> mysql -uroot -proot;(对应用户名和密码)二.SQL语句: 数据定义语言DDL 用来定义数据库.表.列,关 ...
- MySQL加入log_bin报错
MySQL中二进制日志功能默认是关闭的,查看各种开启方式后,确定在配置文件中加入如下配置来开启该功能: [root@bogon /]# more /etc/my.cnf [mysqld] datadi ...
- scrapy 爬取智联招聘
准备工作 1. scrapy startproject Jobs 2. cd Jobs 3. scrapy genspider ZhaopinSpider www.zhaopin.com 4. scr ...
- vue实例的生命周期
Vue实例的生命周期也就是这个实例从出生到死亡的过程,所以我在文档原图上把这个周期大致分为创建过程 | 运行过程 | 销毁过程三个阶段,不同结果或又分为一些小的阶段 在第一个阶段,创建阶段,会完成Vu ...
- css三列布局之双飞翼pk圣杯
三列布局:两边定宽,中间自适应! 看到这个问题,我第一眼想的就是两边定宽float左右,中间加一个margin宽度自适应或者直接设一个overflow:hidden触发bfc机制,这样也可以,看上去也 ...