关于自定义View显示gif图片的问题解决

本文介绍了在自定义View中显示gif图片遇到的问题,即gif动画只显示第一帧。通过修改代码并重点讲解了关键改动,实现了gif动画的正常播放。问题解决的关键在于正确设置和更新Movie对象的时间,并在onDraw方法中强制重绘以达到动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习了gif播放,在网上看到实例自定义view显示gif,于是复制运行一下,结果发现自己的gif图片在第一帧地方就停住了,没有动画效果,尝试着改了一下代码发现真的改好了,虽然不知道为什么,还是很欣喜的记录下,等以后再翻出来看看。

代码复制网址https://www.cnblogs.com/android-blogs/p/5160433.html

代码如下:

步骤1看一下这个工具类的实例代码:MyGifView.java

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Movie;

import android.util.AttributeSet;

import android.view.View;

 

public class MyGifView extends View{

private long movieStart;

private Movie movie;

    //此处必须重写该构造方法

public MyGifView(Context context,AttributeSet attributeSet) {

super(context,attributeSet);

//以文件流(InputStream)读取进gif图片资源

movie=Movie.decodeStream(getResources().openRawResource(R.drawable.keyboard));

}

 

@Override

protected void onDraw(Canvas canvas) {

long curTime=android.os.SystemClock.uptimeMillis();

//第一次播放

if (movieStart == 0) {

movieStart = curTime;

}

if (movie != null) {

int duraction = movie.duration();

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

movie.setTime(relTime);

movie.draw(canvas, 0, 0);

//强制重绘

invalidate();

}

super.onDraw(canvas);

}

}

此工具类中,只做了2件事情。1,构造方法;2,重写了onDraw()方法。大家以后用的话,只需拷贝此类到你的工程下即可起作用。

 

步骤2布局文件代码 activity_main.xml

<LinearLayout 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" >

 

    <TextView 

       android:text="====Gif图片测试布局===="

        android:layout_height="wrap_content"

       android:layout_width="wrap_content"

       />

    

     <com.example.showgifimage.MyGifView 

       android:id="@+id/iv"

       android:layout_height="wrap_content"

       android:layout_width="wrap_content"

       android:layout_margin="20dp"

       /> 

   

</LinearLayout>

布局文件中,注意的是:标签的设置 <com.example.showgifimage.MyGifView/>.

格式:包名+.类名

 

 

步骤3:activity中调用

public class MainActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    }

}

    就这么轻松的把Gif图片显示了~~


在上面的mygifview类里面一句加粗的红字部分是我改动的主要地方,因为在获取gif动画播放的相对时间的截取中,int relTime = (int) ((curTime-movieStart)%duraction);这句话只截取了十几帧,我在这截取的十几帧中每个空隙等间插入了十帧,这样就增加了gif动图播放的帧数,改动之后再运行下来,gif可以正常的播放了,十分流畅。

改动代码如下,黑色加粗部分是改动的重点:

package com.example.tools;

import com.example.stocktrading.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class MyGifView extends View {
private long movieStart;
private Movie movie;

// 此处必须重写该构造方法
public MyGifView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
// 以文件流(InputStream)读取进gif图片资源
movie = Movie.decodeStream(getResources().openRawResource(
R.drawable.cat));
}


@Override
protected void onDraw(Canvas canvas) {
long curTime = android.os.SystemClock.uptimeMillis();// 从开机到现在的毫秒书(手机睡眠的时间不包括在内) 
// 第一次播放
if (movieStart == 0) {
movieStart = curTime;
Log.i("TAG", "wwwww"+movieStart);
}
if (movie != null) {
int time=0;
int n=0;
int duraction = movie.duration();//获得影片完全播放的时间,以秒为单位。
Log.i("TAG", duraction+"yyyyy");
int relTime = (int) ((curTime - movieStart) % duraction);
int m=(relTime-time)/10;
for(int j=0;j<10;j++){
n=time+m*j;
movie.setTime(n);  //这句话保证当前播放的都是对应当前时间的画面。
Log.i("TAG", n+"xxyyx");
movie.draw(canvas, 0, 0);
// 强制重绘,为什么这个重绘一定要放在for循环中才重绘 啊,之前没有都只画一遍就不画了
}

// for(int i=0;i<3;i++){
// movie.setTime(relTime);
// Log.i("TAG", relTime+"xxyyx");
// movie.draw(canvas, 0, 0);
// }
// 为什么这个就显示gif不动呢,是因为relTime的数据太少了吗,只有十几个数据,我在上面的for循环中插入了十个点,一共是一百多个数据,是这个原因吗,不是因为没有重画的原因吗
time=relTime;
}
invalidate();
//这里是绘制此gif的某一帧,并刷新本身,从而又调起了onDraw方法,如此动画的效果就达到了。
super.onDraw(canvas);
}

}

以上就是问题解决的一个方案,虽然还云里雾里,哈哈菜鸟一枚,发表再次希望大神看到可以指点一二。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值