这里有两种播放GIF动画效果的示例,第一种GIF示例,可以处理事件
package com.example.gifviewdemo; import android.app.Activity; public class MainActivity extends Activity implements OnClickListener { GifView gf1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 从xml中得到GifView的句柄 gf1 = (GifView) findViewById(R.id.gif2); // 设置Gif图片源 gf1.setGifImage(R.drawable.ttt); // 添加监听器 gf1.setOnClickListener(this); // 设置显示的大小,拉伸或者压缩 gf1.setShowDimension(300, 300); // 设置加载方式:先加载后显示、边加载边显示、只显示第一帧再显示 gf1.setGifImageType(GifImageType.COVER); gf1.showAnimation(); } @Override public void onClick(View v) { // TODO Auto-generated method stub } }
<RelativeLayout 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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.gifviewdemo.MainActivity" > <com.ant.liao.GifView android:id="@+id/gif2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:enabled="false" android:paddingLeft="14px" android:paddingTop="4px" /> </RelativeLayout>
第二种方法
GIFMovieView.java类
package com.basv.gifmoviewview.widget; import android.annotation.SuppressLint; /** * This is a View class that wraps Android {@link Movie} object and displays it. * You can set GIF as a Movie object or as a resource id from XML or by calling * {@link #setMovie(Movie)} or {@link #setMovieResource(int)}. * <p> * You can pause and resume GIF animation by calling {@link #setPaused(boolean)}. * <p> * The animation is drawn in the center inside of the measured view bounds. * * @author Sergey Bakhtiarov */ public class GifMovieView extends View { private static final int DEFAULT_MOVIEW_DURATION = 1000; private int mMovieResourceId; private Movie mMovie; private long mMovieStart; private int mCurrentAnimationTime = 0; /** * Position for drawing animation frames in the center of the view. */ private float mLeft; private float mTop; /** * Scaling factor to fit the animation within view bounds. */ private float mScale; /** * Scaled movie frames width and height. */ private int mMeasuredMovieWidth; private int mMeasuredMovieHeight; private volatile boolean mPaused = false; private boolean mVisible = true; public GifMovieView(Context context) { this(context, null); } public GifMovieView(Context context, AttributeSet attrs) { this(context, attrs, R.styleable.CustomTheme_gifMoviewViewStyle); } public GifMovieView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setViewAttributes(context, attrs, defStyle); } @SuppressLint("NewApi") private void setViewAttributes(Context context, AttributeSet attrs, int defStyle) { /** * Starting from HONEYCOMB have to turn off HW acceleration to draw * Movie on Canvas. */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GifMoviewView, defStyle, R.style.Widget_GifMoviewView); mMovieResourceId = array.getResourceId(R.styleable.GifMoviewView_gif, -1); mPaused = array.getBoolean(R.styleable.GifMoviewView_paused, false); array.recycle(); if (mMovieResourceId != -1) { mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId)); } } public void setMovieResource(int movieResId) { this.mMovieResourceId = movieResId; mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId)); requestLayout(); } public void setMovie(Movie movie) { this.mMovie = movie; requestLayout(); } public Movie getMovie() { return mMovie; } public void setMovieTime(int time) { mCurrentAnimationTime = time; invalidate(); } public void setPaused(boolean paused) { this.mPaused = paused; /** * Calculate new movie start time, so that it resumes from the same * frame. */ if (!paused) { mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime; } invalidate(); } public boolean isPaused() { return this.mPaused; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mMovie != null) { int movieWidth = mMovie.width(); int movieHeight = mMovie.height(); /* * Calculate horizontal scaling */ float scaleH = 1f; int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec); if (measureModeWidth != MeasureSpec.UNSPECIFIED) { int maximumWidth = MeasureSpec.getSize(widthMeasureSpec); if (movieWidth > maximumWidth) { scaleH = (float) movieWidth / (float) maximumWidth; } } /* * calculate vertical scaling */ float scaleW = 1f; int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec); if (measureModeHeight != MeasureSpec.UNSPECIFIED) { int maximumHeight = MeasureSpec.getSize(heightMeasureSpec); if (movieHeight > maximumHeight) { scaleW = (float) movieHeight / (float) maximumHeight; } } /* * calculate overall scale */ mScale = 1f / Math.max(scaleH, scaleW); mMeasuredMovieWidth = (int) (movieWidth * mScale); mMeasuredMovieHeight = (int) (movieHeight * mScale); setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight); } else { /* * No movie set, just set minimum available size. */ setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight()); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); /* * Calculate left / top for drawing in center */ mLeft = (getWidth() - mMeasuredMovieWidth) / 2f; mTop = (getHeight() - mMeasuredMovieHeight) / 2f; mVisible = getVisibility() == View.VISIBLE; } @Override protected void onDraw(Canvas canvas) { if (mMovie != null) { if (!mPaused) { updateAnimationTime(); drawMovieFrame(canvas); invalidateView(); } else { drawMovieFrame(canvas); } } } /** * Invalidates view only if it is visible. * <br> * {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher. * */ @SuppressLint("NewApi") private void invalidateView() { if(mVisible) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { postInvalidateOnAnimation(); } else { invalidate(); } } } /** * 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_MOVIEW_DURATION; } mCurrentAnimationTime = (int) ((now - mMovieStart) % dur); } /** * 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, mLeft / mScale, mTop / mScale); canvas.restore(); } @SuppressLint("NewApi") @Override public void onScreenStateChanged(int screenState) { super.onScreenStateChanged(screenState); mVisible = screenState == SCREEN_STATE_ON; invalidateView(); } @SuppressLint("NewApi") @Override protected void onVisibilityChanged(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(); } }
mainactivity.java
package com.basv.gifmoviewview; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final GifMovieView gif1 = (GifMovieView) findViewById(R.id.gif1); gif1.setMovieResource(R.drawable.ttt); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void onGifClick(View v) { GifMovieView gif = (GifMovieView) v; gif.setPaused(!gif.isPaused()); } }
attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="GifMoviewView"> <attr name="gif" format="reference" /> <attr name="paused" format="boolean" /> </declare-styleable> <declare-styleable name="CustomTheme"> <attr name="gifMoviewViewStyle" format="reference" /> </declare-styleable> </resources>
styles.xml
<resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> <style name="AppBaseTheme" parent="android:Theme.Light"> <!-- Theme customizations available in newer API levels can go in res/values-vXX/styles.xml, while customizations related to backward-compatibility can go here. --> </style> <!-- Application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> </style> <style name="Widget.GifMoviewView" parent="@android:style/Widget"></style> </resources>
main.xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.basv.gifmoviewview" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFFFF" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <com.basv.gifmoviewview.widget.GifMovieView android:id="@+id/gif1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onGifClick" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <com.basv.gifmoviewview.widget.GifMovieView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onGifClick" custom:gif="@drawable/ddd" /> <com.basv.gifmoviewview.widget.GifMovieView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onGifClick" custom:gif="@drawable/aaa" /> <com.basv.gifmoviewview.widget.GifMovieView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onGifClick" custom:gif="@drawable/gif_heart" /> <com.basv.gifmoviewview.widget.GifMovieView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="onGifClick" custom:gif="@drawable/gif_heart" /> </LinearLayout> </LinearLayout> </ScrollView>
这两种方法最后达到的效果是一样的
方便以后项目中有需要GIF动画的时候,直接用
demo如下:百度网盘
https://pan.baidu.com/disk/home?
相关推荐
本篇文章将深入探讨“gif动画播放”的相关知识点,帮助你理解其工作原理以及如何实现播放。 首先,GIF动画是由一系列连续的静态图像帧组成的。每个帧都包含了一个时间延迟,决定了该帧显示的时间长度。当这些帧按照...
实现“可暂停播放”的GIF动画效果通常有两种方法: 1. JavaScript或HTML5 API:通过JavaScript库如jQuery或者使用HTML5的Canvas元素,可以捕获GIF的每一帧并手动控制播放。当用户触发暂停事件时,程序会停止更新...
开发者可以通过编程接口设定GIF动画的播放速度,既可以加快播放速率,也可以减慢速度,甚至可以暂停和重新启动动画。这种灵活性使得开发者可以根据用户体验或者应用需求来调整动画节奏,增强交互性。 在实现上,这...
6. **控制GIF状态**:为了实现更精细的控制,可以使用`pictureBox1.ImageAnimator`对象,该对象提供了控制GIF动画的方法。例如,`pictureBox1.ImageAnimator.HasAnimation`判断是否为动画,`pictureBox1....
"一个支持GIF和APNG的统一动画播放组件"是为了解决开发者在处理这两种格式时面临的兼容性和效率问题而设计的。这个组件能够无缝地在Android和Java Swing环境中播放GIF和APNG动画,极大地简化了开发流程。在Android...
在Android中,有两种主要的方法来播放Gif动画:使用ImageView的扩展库和使用GifDecoder或GIFDrawable。 1. **使用第三方库**: - **Glide**:Glide是一个强大的图片加载库,它不仅支持静态图片,也支持Gif动画。只...
属性动画(Property Animation)和GIF动画是两种常用的动画实现方式,各有其特点和应用场景。本文将详细介绍这两种动画的使用方法,并结合一个名为"MyApplication"的项目实例进行讲解。 一、属性动画(Property ...
在Windows编程领域,GDI+(Graphics Device Interface Plus)是一个强大的图形处理库,它扩展了传统的GDI功能,提供了更多的...通过封装这些功能,开发者可以在自己的应用程序中方便地集成GIF动画播放,提升用户体验。
在Android平台上,播放GIF动画是一项常见的需求,无论是用于加载指示、表情符号还是其他互动元素。GIF是一种支持多帧的图像格式,...通过不断地实践和学习,开发者可以掌握更多关于Android中GIF动画播放的高级技巧。
1. **GIF动画播放**: 在Android中,播放GIF动画通常有两种方式:使用Android自带的`ImageView`(不支持GIF)配合第三方库,或者直接使用支持GIF的库。常见的库有`Glide`、`Picasso`和`Android-Universal-Image-...
根据显示方式,进度条可分为两种主要类型:确定性和不确定性的。确定性进度条会明确显示出任务完成的百分比,如下载或安装进度;不确定性进度条(如旋转圆圈)则表示任务正在执行,但无法精确预测何时结束,常用于...
在Android中,通常有两种主流方法来显示GIF动画: 1. 使用第三方库:例如,Android-Universal-Image-Loader、Glide、Picasso等图片加载库都提供了对GIF的支持。这些库内部会解析GIF文件并逐帧绘制到Canvas上。这种...
3. **帧间优化**:在GIF动画中,每一帧都可以基于前一帧进行差异编码,只存储两帧之间的变化部分。这种差分编码可以大大减小动画的大小,因为大部分动画帧只是轻微变化。此外,还可以通过删除不必要帧或优化帧顺序来...
因此,在制作过程中,应考虑压缩和减少帧数,优化颜色方案,甚至使用二值化(仅两种颜色)来减小文件大小。 10. **应用场景**:GIF动画广泛应用于社交媒体、网站、教育、娱乐、广告等多个领域,如表情包、教程演示...
标题 "C++_wince_gif_动画" 涉及到的是在Windows CE (WinCE)平台上使用C++编程语言实现GIF动画播放的技术。WinCE是一个嵌入式操作系统,广泛应用于移动设备和嵌入式系统。在这个项目中,开发者提供了一套源代码,...
为了解决这个问题,你可以选择以下两种方法: 1. **使用第三方库:** - `FreeImage`是一个开源库,它提供了对多种图像格式的支持,包括GIF的读取和处理。你可以通过NuGet包管理器安装`FreeImage.WPF`,然后使用它...
2. **GIF显示**:在Android上显示GIF有两种主要方法。一是使用WebView组件,虽然功能强大但可能导致性能问题;二是使用支持GIF的ImageView扩展,如上述提到的第三方库,它们通常提供更优化的性能和更好的控制。 3. ...
5. **动画播放**: - **计时器**:为了播放动画,需要一个计时器来控制帧之间的延迟。 - **缓冲区管理**:每帧的数据需要存储在一个缓冲区中,以便在屏幕上显示。 - **重绘**:根据帧的信息更新屏幕上的图像,...
在Android中,处理GIF主要有两种方式:`GifDrawable`和`GIFView`。`GifDrawable`是从Android 4.3(API级别18)开始引入的,可以直接从`InputStream`加载GIF并绘制到`BitmapDrawable`上。而`GIFView`通常是开发者...
在iOS中,有两种主要方式实现GIF动画: 1. **使用UIImage**:虽然`UIImage`不直接支持GIF,但可以通过第三方库如`Kingfisher`或`SDWebImage`加载并播放GIF。这些库会自动处理GIF动画的帧切换。 2. **使用UIView和...