[Android] VideoGridFragment: determine at runtime the best viewing mode

Ludovic Fauvet git at videolan.org
Mon Oct 8 23:15:06 CEST 2012


vlc-ports/android | branch: master | Ludovic Fauvet <etix at videolan.org> | Mon Oct  8 20:43:09 2012 +0200| [fb93861845e4c539f657a21776216c5631b5cc29] | committer: Ludovic Fauvet

VideoGridFragment: determine at runtime the best viewing mode

    Because of a broken GridView API we're not able to get the number of
columns the GridView is able to show without laying it out first. And
reconfiguring it to switch from list to grid (and vice versa) is also a
pain in the ass because of the poorly designed getNumColumns method.
    Therefore we are forced to compute manually, using constants
(because on Android you can't query the XML), the needed size to show at
least two columns. Otherwise we have switch to the list mode.

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

 vlc-android/res/layout/video_grid.xml              |    3 -
 .../videolan/vlc/gui/video/VideoGridFragment.java  |   91 ++++++++++++++++----
 .../videolan/vlc/gui/video/VideoListAdapter.java   |    5 +-
 3 files changed, 75 insertions(+), 24 deletions(-)

diff --git a/vlc-android/res/layout/video_grid.xml b/vlc-android/res/layout/video_grid.xml
index 1471102..c20ea3d 100644
--- a/vlc-android/res/layout/video_grid.xml
+++ b/vlc-android/res/layout/video_grid.xml
@@ -13,9 +13,6 @@
         android:scrollbarStyle="outsideInset"
         android:numColumns="auto_fit"
         android:fastScrollEnabled="true"
-        android:horizontalSpacing="20dp"
-        android:verticalSpacing="20dp"
-        android:stretchMode="spacingWidth"
         android:background="@drawable/background_pattern_dark_repeat"
         android:gravity="center" />
 
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 9681956..8c06d87 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoGridFragment.java
@@ -31,22 +31,25 @@ import org.videolan.vlc.Media;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.R;
 import org.videolan.vlc.ThumbnailerManager;
+import org.videolan.vlc.Util;
 import org.videolan.vlc.VlcRunnable;
 import org.videolan.vlc.WeakHandler;
 import org.videolan.vlc.gui.CommonDialogs;
 import org.videolan.vlc.gui.PreferencesActivity;
 import org.videolan.vlc.interfaces.ISortable;
 
-import android.annotation.TargetApi;
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -68,6 +71,16 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
     protected static final String ACTION_SCAN_STOP = "org.videolan.vlc.gui.ScanStop";
     protected static final int UPDATE_ITEM = 0;
 
+    /* Constants used to switch from Grid to List and vice versa */
+    //FIXME If you know a way to do this in pure XML please do it!
+    private static final int GRID_ITEM_WIDTH_DP = 156;
+    private static final int GRID_HORIZONTAL_SPACING_DP = 20;
+    private static final int GRID_VERTICAL_SPACING_DP = 20;
+    private static final int GRID_STRETCH_MODE = GridView.STRETCH_SPACING;
+    private static final int LIST_HORIZONTAL_SPACING_DP = 0;
+    private static final int LIST_VERTICAL_SPACING_DP = 10;
+    private static final int LIST_STRETCH_MODE = GridView.STRETCH_COLUMN_WIDTH;
+
     protected LinearLayout mLayoutFlipperLoading;
     protected TextView mTextViewNomedia;
     protected Media mItemToUpdate;
@@ -89,7 +102,6 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
     }
 
     @Override
-    @TargetApi(11)
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
     {
         View v = inflater.inflate(R.layout.video_grid, container, false);
@@ -98,23 +110,6 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
         mLayoutFlipperLoading = (LinearLayout) v.findViewById(R.id.layout_flipper_loading);
         mTextViewNomedia = (TextView) v.findViewById(R.id.textview_nomedia);
 
-        /* Determine if we need to show items in list or grid */
-        int columns = 1;
-        GridView gv = (GridView)v.findViewById(android.R.id.list);
-        if (android.os.Build.VERSION.SDK_INT >= 11)
-            columns = gv.getNumColumns();
-
-        float density = getResources().getDisplayMetrics().density;
-        if (columns == 1) {
-            gv.setNumColumns(1);
-            gv.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
-            gv.setHorizontalSpacing(0);
-            gv.setVerticalSpacing((int) (10 * density + 0.5f));
-            mVideoAdapter.setListMode(true);
-        } else {
-            gv.setColumnWidth((int) (150 * density + 0.5f));
-        }
-
         return v;
     }
 
@@ -152,6 +147,7 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
         mVideoAdapter.setLastMedia(lastPath, times);
         mVideoAdapter.notifyDataSetChanged();
         mMediaLibrary.addUpdateHandler(mHandler);
+        updateViewMode();
     }
 
     @Override
@@ -167,6 +163,63 @@ public class VideoGridFragment extends SherlockGridFragment implements ISortable
         mVideoAdapter.clear();
     }
 
+    private boolean hasSpaceForGrid() {
+        final Activity activity = getActivity();
+        if (activity == null)
+            return true;
+
+        final LayoutInflater inflater = (LayoutInflater)activity.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        final View v = inflater.inflate(R.layout.video_grid, null);
+        final GridView grid = (GridView)v.findViewById(android.R.id.list);
+
+        DisplayMetrics outMetrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
+
+        final int itemWidth = Util.convertDpToPx(GRID_ITEM_WIDTH_DP);
+        final int horizontalspacing = Util.convertDpToPx(GRID_HORIZONTAL_SPACING_DP);
+        final int width = grid.getPaddingLeft() + grid.getPaddingRight() + horizontalspacing + (itemWidth * 2);
+        if (width < outMetrics.widthPixels)
+            return true;
+        return false;
+    }
+
+    private void updateViewMode() {
+        if (getView() == null) {
+            Log.w(TAG, "Unable to setup the view");
+            return;
+        }
+
+        final GridView gv = (GridView)getView().findViewById(android.R.id.list);
+        if (hasSpaceForGrid()) {
+            Log.d(TAG, "Switching to grid mode");
+            gv.setNumColumns(GridView.AUTO_FIT);
+            gv.setStretchMode(GRID_STRETCH_MODE);
+            gv.setHorizontalSpacing(Util.convertDpToPx(GRID_HORIZONTAL_SPACING_DP));
+            gv.setVerticalSpacing(Util.convertDpToPx(GRID_VERTICAL_SPACING_DP));
+            gv.setColumnWidth(Util.convertDpToPx(GRID_ITEM_WIDTH_DP));
+            mVideoAdapter.setListMode(false);
+        } else {
+            Log.e(TAG, "Switching to list mode");
+            gv.setNumColumns(1);
+            gv.setStretchMode(LIST_STRETCH_MODE);
+            gv.setHorizontalSpacing(LIST_HORIZONTAL_SPACING_DP);
+            gv.setVerticalSpacing(Util.convertDpToPx(LIST_VERTICAL_SPACING_DP));
+            mVideoAdapter.setListMode(true);
+        }
+        gv.forceLayout();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE ||
+            newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
+            updateViewMode();
+        }
+    }
+
     @Override
     public void onGridItemClick(GridView l, View v, int position, long id) {
         playVideo(position);
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 1e77529..3f11115 100644
--- a/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/video/VideoListAdapter.java
@@ -124,10 +124,9 @@ public class VideoListAdapter extends ArrayAdapter<Media>
      */
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
-
         ViewHolder holder;
         View v = convertView;
-        if (v == null) {
+        if (v == null || (((ViewHolder)v.getTag()).listmode != mListMode)) {
             LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             if (!mListMode)
                 v = inflater.inflate(R.layout.video_grid_item, parent, false);
@@ -138,6 +137,7 @@ public class VideoListAdapter extends ArrayAdapter<Media>
             holder.thumbnail = (ImageView) v.findViewById(R.id.ml_item_thumbnail);
             holder.title = (TextView) v.findViewById(R.id.ml_item_title);
             holder.subtitle = (TextView) v.findViewById(R.id.ml_item_subtitle);
+            holder.listmode = mListMode;
             v.setTag(holder);
             /* Set the layoutParams based on the values set in the video_grid_item.xml root element */
             v.setLayoutParams(new GridView.LayoutParams(v.getLayoutParams().width, v.getLayoutParams().height));
@@ -185,6 +185,7 @@ public class VideoListAdapter extends ArrayAdapter<Media>
     }
 
     static class ViewHolder {
+        boolean listmode;
         View layout;
         ImageView thumbnail;
         TextView title;



More information about the Android mailing list