binbinyyang---Android实现显示GIF图片

来源:互联网 发布:象棋等级分算法 编辑:程序博客网 时间:2024/06/05 04:34

最近.一个朋友跟我说想,我给她弄个闹钟APP软件...功能其实很简单...只需要弄个简单的闹钟.自己设计设计时间.然后时间到了的时候,闹铃放的声音是男朋友录制好的声音...于是就开始整了....

第一次做这种的时候.我想把首页界面做成一个GIF动画特效的.这样看起来可爱点...适合妹子用,于是就有了下面这个效果图

  


上代码

ndroid中的Android.graphics.Movie 这个类,这是android提供给我们的一个非常方便的工具。

首先,重写控件View,自定义一个展示gif图的GifView

Movie其实管理着GIF动画中的多个帧,只需要通过 setTime() 一下就可以让它在draw()的时候绘出相应的那帧图像。通过当前时间与duration之间的换算关系,是很容易实现GIF动起来的效果。
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public class GifView extends View {    
  2.     
  3.     /**  
  4.      * 默认为1秒  
  5.      */    
  6.     private static final int DEFAULT_MOVIE_DURATION = 1000;    
  7.     
  8.     private int mMovieResourceId;    
  9.     
  10.     private Movie mMovie;    
  11.     
  12.     private long mMovieStart;    
  13.     
  14.     private int mCurrentAnimationTime = 0;    
  15.     
  16.     private float mLeft;    
  17.     
  18.     private float mTop;    
  19.     
  20.     private float mScale;    
  21.     
  22.     private int mMeasuredMovieWidth;    
  23.     
  24.     private int mMeasuredMovieHeight;    
  25.     
  26.     private boolean mVisible = true;    
  27.     
  28.     private volatile boolean mPaused = false;    
  29.     
  30.     public GifView(Context context) {    
  31.         this(context, null);    
  32.     }    
  33.     
  34.     public GifView(Context context, AttributeSet attrs) {    
  35.         this(context, attrs, R.styleable.CustomTheme_gifViewStyle);    
  36.     }    
  37.     
  38.     public GifView(Context context, AttributeSet attrs, int defStyle) {    
  39.         super(context, attrs, defStyle);    
  40.         setViewAttributes(context, attrs, defStyle);    
  41.     }    
  42.     
  43.     @SuppressLint("NewApi")    
  44.     private void setViewAttributes(Context context, AttributeSet attrs,    
  45.             int defStyle) {    
  46.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {    
  47.             setLayerType(View.LAYER_TYPE_SOFTWARE, null);    
  48.         }    
  49.         // 从描述文件中读出gif的值,创建出Movie实例    
  50.         final TypedArray array = context.obtainStyledAttributes(attrs,    
  51.                 R.styleable.GifView, defStyle, R.style.Widget_GifView);    
  52.         mMovieResourceId = array.getResourceId(R.styleable.GifView_gif, -1);    
  53.         mPaused = array.getBoolean(R.styleable.GifView_paused, false);    
  54.         array.recycle();    
  55.         if (mMovieResourceId != -1) {    
  56.             mMovie = Movie.decodeStream(getResources().openRawResource(    
  57.                     mMovieResourceId));    
  58.         }    
  59.     }    
  60.     
  61.     /**  
  62.      * 设置gif图资源  
  63.      *   
  64.      * @param movieResId  
  65.      */    
  66.     public void setMovieResource(int movieResId) {    
  67.         this.mMovieResourceId = movieResId;    
  68.         mMovie = Movie.decodeStream(getResources().openRawResource(    
  69.                 mMovieResourceId));    
  70.         requestLayout();    
  71.     }    
  72.     
  73.     public void setMovie(Movie movie) {    
  74.         this.mMovie = movie;    
  75.         requestLayout();    
  76.     }    
  77.     
  78.     public Movie getMovie() {    
  79.         return mMovie;    
  80.     }    
  81.     
  82.     public void setMovieTime(int time) {    
  83.         mCurrentAnimationTime = time;    
  84.         invalidate();    
  85.     }    
  86.     
  87.     /**  
  88.      * 设置暂停  
  89.      *   
  90.      * @param paused  
  91.      */    
  92.     public void setPaused(boolean paused) {    
  93.         this.mPaused = paused;    
  94.         if (!paused) {    
  95.             mMovieStart = android.os.SystemClock.uptimeMillis()    
  96.                     - mCurrentAnimationTime;    
  97.         }    
  98.         invalidate();    
  99.     }    
  100.     
  101.     /**  
  102.      * 判断gif图是否停止了  
  103.      *   
  104.      * @return  
  105.      */    
  106.     public boolean isPaused() {    
  107.         return this.mPaused;    
  108.     }    
  109.     
  110.     @Override    
  111.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
  112.         if (mMovie != null) {    
  113.             int movieWidth = mMovie.width();    
  114.             int movieHeight = mMovie.height();    
  115.             int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);    
  116.             float scaleW = (float) movieWidth / (float) maximumWidth;    
  117.             mScale = 1f / scaleW;    
  118.             mMeasuredMovieWidth = maximumWidth;    
  119.             mMeasuredMovieHeight = (int) (movieHeight * mScale);    
  120.             setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);    
  121.         } else {    
  122.             setMeasuredDimension(getSuggestedMinimumWidth(),    
  123.                     getSuggestedMinimumHeight());    
  124.         }    
  125.     }    
  126.     
  127.     @Override    
  128.     protected void onLayout(boolean changed, int l, int t, int r, int b) {    
  129.         super.onLayout(changed, l, t, r, b);    
  130.         mLeft = (getWidth() - mMeasuredMovieWidth) / 2f;    
  131.         mTop = (getHeight() - mMeasuredMovieHeight) / 2f;    
  132.         mVisible = getVisibility() == View.VISIBLE;    
  133.     }    
  134.     
  135.     @Override    
  136.     protected void onDraw(Canvas canvas) {    
  137.         if (mMovie != null) {    
  138.             if (!mPaused) {    
  139.                 updateAnimationTime();    
  140.                 drawMovieFrame(canvas);    
  141.                 invalidateView();    
  142.             } else {    
  143.                 drawMovieFrame(canvas);    
  144.             }    
  145.         }    
  146.     }    
  147.     
  148.     @SuppressLint("NewApi")    
  149.     private void invalidateView() {    
  150.         if (mVisible) {    
  151.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    
  152.                 postInvalidateOnAnimation();    
  153.             } else {    
  154.                 invalidate();    
  155.             }    
  156.         }    
  157.     }    
  158.     
  159.     private void updateAnimationTime() {    
  160.         long now = android.os.SystemClock.uptimeMillis();    
  161.         // 如果第一帧,记录起始时间    
  162.         if (mMovieStart == 0) {    
  163.             mMovieStart = now;    
  164.         }    
  165.         // 取出动画的时长    
  166.         int dur = mMovie.duration();    
  167.         if (dur == 0) {    
  168.             dur = DEFAULT_MOVIE_DURATION;    
  169.         }    
  170.         // 算出需要显示第几帧    
  171.         mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);    
  172.     }    
  173.     
  174.     private void drawMovieFrame(Canvas canvas) {    
  175.         // 设置要显示的帧,绘制即可    
  176.         mMovie.setTime(mCurrentAnimationTime);    
  177.         canvas.save(Canvas.MATRIX_SAVE_FLAG);    
  178.         canvas.scale(mScale, mScale);    
  179.         mMovie.draw(canvas, mLeft / mScale, mTop / mScale);    
  180.         canvas.restore();    
  181.     }    
  182.     
  183.     @SuppressLint("NewApi")    
  184.     @Override    
  185.     public void onScreenStateChanged(int screenState) {    
  186.         super.onScreenStateChanged(screenState);    
  187.         mVisible = screenState == SCREEN_STATE_ON;    
  188.         invalidateView();    
  189.     }    
  190.     
  191.     @SuppressLint("NewApi")    
  192.     @Override    
  193.     protected void onVisibilityChanged(View changedView, int visibility) {    
  194.         super.onVisibilityChanged(changedView, visibility);    
  195.         mVisible = visibility == View.VISIBLE;    
  196.         invalidateView();    
  197.     }    
  198.     
  199.     @Override    
  200.     protected void onWindowVisibilityChanged(int visibility) {    
  201.         super.onWindowVisibilityChanged(visibility);    
  202.         mVisible = visibility == View.VISIBLE;    
  203.         invalidateView();    
  204.     }    
  205.     
  206. }    

其次,在xml布局文件中,把这个view定义进去,代码如下:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.               android:layout_width="fill_parent"  
  3.               android:layout_height="fill_parent"  
  4.               android:background="#ffffff"  
  5.               android:gravity="center"  
  6.               android:orientation="vertical"  
  7.     >  
  8.   
  9.   
  10.     <com.example.alarmtest.GifView  
  11.         android:id="@+id/gif1"  
  12.         android:layout_width="300dp"  
  13.         android:layout_height="300dp"  
  14.         android:layout_gravity="center_horizontal"  
  15.         android:enabled="false"/>  
  16.   
  17.     <Button  
  18.         android:id="@+id/bu"  
  19.         android:text="进入"  
  20.         android:layout_width="wrap_content"  
  21.         android:layout_height="wrap_content"  
  22.         android:layout_gravity="center_horizontal"/>  
  23.   
  24. </LinearLayout>  

最后,在MainActivity中的使用,代码如下:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public class FirstActivity extends Activity {  
  2.   
  3.   
  4.     private GifView gif;  
  5.   
  6.     @Override  
  7.     protected void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.activity_first);  
  10.   
  11.         gif = (GifView) findViewById(R.id.gif1);  
  12.         // 设置背景gif图片资源  
  13.         gif.setMovieResource(R.raw.a123);  
  14.   
  15.     }  
  16.   
  17. }  
Styles.xml

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <declare-styleable name="GifView">  
  2.         <attr name="gif" format="reference" />  
  3.         <attr name="paused" format="boolean" />  
  4.     </declare-styleable>  
  5.     <declare-styleable name="CustomTheme">  
  6.         <attr name="gifViewStyle" format="reference" />  
  7.     </declare-styleable>  
  8.   
  9.     <style name="Widget_GifView"></style>  



raw是res下面的一个文件放的是GIF动画图噢

我这里放了一个动画图 跟一个 音乐文件,因为我要做的是一个有声音的闹铃



0 0