[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