[Android] GridView: add nifty animations

Ludovic Fauvet git at videolan.org
Fri Oct 12 00:31:47 CEST 2012


vlc-ports/android | branch: master | Ludovic Fauvet <etix at videolan.org> | Fri Oct 12 00:29:01 2012 +0200| [69783c0a9a8f3cfe9c918aa42db12fd719d41a00] | committer: Ludovic Fauvet

GridView: add nifty animations

> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=69783c0a9a8f3cfe9c918aa42db12fd719d41a00
---

 .../videolan/vlc/gui/video/VideoGridAnimator.java  |  154 ++++++++++++++++++++
 .../videolan/vlc/gui/video/VideoGridFragment.java  |    9 +-
 .../videolan/vlc/gui/video/VideoListAdapter.java   |    4 +
 3 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoGridAnimator.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoGridAnimator.java
new file mode 100644
index 0000000..a1436bc
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoGridAnimator.java
@@ -0,0 +1,154 @@
+/*****************************************************************************
+ * VideoGridAnimator.java
+ *****************************************************************************
+ * Copyright © 2011-2012 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.vlc.gui.video;
+
+import android.annotation.TargetApi;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.OvershootInterpolator;
+import android.view.animation.TranslateAnimation;
+import android.view.animation.Animation.AnimationListener;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class VideoGridAnimator {
+
+    public final static String TAG = "VLC/VideoGridAnimator";
+
+    private final GridView mGridView;
+    private boolean isAnimating = false;
+    private int mLastNItems;
+    private int mAnimationsRunning = 0;
+
+    public VideoGridAnimator(GridView gridview) {
+        mGridView = gridview;
+        mGridView.setOnHierarchyChangeListener(mHCL);
+    }
+
+    public void animate() {
+        isAnimating = true;
+        mLastNItems = -1;
+        mGridView.removeCallbacks(r);
+        mGridView.post(r);
+    }
+
+    OnHierarchyChangeListener mHCL = new OnHierarchyChangeListener() {
+        @Override
+        public void onChildViewRemoved(View parent, View child) {
+            // TODO Auto-generated method stub
+        }
+
+        @Override
+        public void onChildViewAdded(View parent, View child) {
+            if (isAnimating && parent == mGridView)
+                setAlpha(0, child);
+        }
+    };
+
+    final Runnable r = new Runnable() {
+        @Override
+        public void run() {
+            if (mGridView.getChildCount() != mLastNItems) {
+                mLastNItems = mGridView.getChildCount();
+                Log.e(TAG, "Rescheduling animation: list not ready");
+                mGridView.postDelayed(this, 10);
+                return;
+            }
+
+            isAnimating = false;
+
+            for (int i = 0; i < mGridView.getChildCount(); i++) {
+                AnimationSet animSet = new AnimationSet(true);
+                Animation animation = new AlphaAnimation(0.0f, 1.0f);
+                animation.setDuration(400);
+                animation.setStartOffset(i * 80);
+                animSet.addAnimation(animation);
+                if (((VideoListAdapter)mGridView.getAdapter()).isListMode()) {
+                    animation = new TranslateAnimation(
+                            Animation.RELATIVE_TO_SELF, -1.0f,Animation.RELATIVE_TO_SELF, 0.0f,
+                            Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f
+                        );
+                    animation.setDuration(400);
+                    animation.setStartOffset(i * 80);
+                    animSet.addAnimation(animation);
+                }
+                animSet.setInterpolator(new OvershootInterpolator());
+                animSet.setAnimationListener(new AnimationListener() {
+
+                    @Override
+                    public void onAnimationStart(Animation animation) {
+                        mAnimationsRunning += 1;
+                    }
+
+                    @Override
+                    public void onAnimationRepeat(Animation animation) {
+                        // TODO Auto-generated method stub
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animation animation) {
+                        mAnimationsRunning -= 1;
+                    }
+                });
+                isAnimating = false;
+                View v = mGridView.getChildAt(i);
+                setAlpha(1, v);
+                v.startAnimation(animSet);
+            }
+        }
+    };
+
+    public boolean isAnimationDone() {
+        return mAnimationsRunning == 0;
+    }
+
+    /* Support pre-11 device */
+    @TargetApi(11)
+    public void setAlpha(float alpha, View view)
+    {
+        if (android.os.Build.VERSION.SDK_INT >= 11)
+            view.setAlpha(alpha);
+        else if (view instanceof ViewGroup)
+        {
+            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++)
+            {
+                setAlpha(alpha, ((ViewGroup) view).getChildAt(i));
+                if (((ViewGroup) view).getBackground() != null) ((ViewGroup) view).getBackground().setAlpha((int) (alpha * 255));
+            }
+        }
+        else if (view instanceof ImageView)
+        {
+            if (((ImageView) view).getDrawable() != null) ((ImageView) view).getDrawable().setAlpha((int) (alpha * 255));
+            if (((ImageView) view).getBackground() != null) ((ImageView) view).getBackground().setAlpha((int) (alpha * 255));
+        }
+        else if (view instanceof TextView)
+        {
+            ((TextView) view).setTextColor(((TextView) view).getTextColors().withAlpha((int) (alpha * 255)));
+            if (((TextView) view).getBackground() != null) ((TextView) view).getBackground().setAlpha((int) (alpha * 255));
+        }
+    }
+}
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java
index b4920b3..a95f372 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java
@@ -89,6 +89,7 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
     private VideoListAdapter mVideoAdapter;
     private MediaLibrary mMediaLibrary;
     private ThumbnailerManager mThumbnailerManager;
+    private VideoGridAnimator mAnimator;
 
     /* All subclasses of Fragment must include a public empty constructor. */
     public VideoGridFragment() { }
@@ -129,6 +130,7 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
         }
 
         updateList();
+        mAnimator = new VideoGridAnimator(getGridView());
     }
 
     @Override
@@ -148,6 +150,7 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
         mVideoAdapter.notifyDataSetChanged();
         mMediaLibrary.addUpdateHandler(mHandler);
         updateViewMode();
+        mAnimator.animate();
     }
 
     @Override
@@ -293,7 +296,11 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
                 fragment.updateItem();
                 break;
             case MediaLibrary.MEDIA_ITEMS_UPDATED:
-                fragment.updateList();
+                // Don't update the adapter while the layout animation is running
+                if (fragment.mAnimator.isAnimationDone())
+                    fragment.updateList();
+                else
+                    sendEmptyMessageDelayed(msg.what, 500);
                 break;
             }
         }
diff --git a/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java b/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java
index 3f11115..c8d90fb 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java
@@ -196,4 +196,8 @@ public class VideoListAdapter extends ArrayAdapter<Media>
     public void setListMode(boolean value) {
         mListMode = value;
     }
+
+    public boolean isListMode() {
+        return mListMode;
+    }
 }



More information about the Android mailing list