瀏覽代碼

Recovered ExtendedListView; ExtendedListFragment updated to handle to possible layouts

David A. Velasco 10 年之前
父節點
當前提交
2cfed6eaa7

+ 22 - 5
res/layout/list_fragment.xml

@@ -24,16 +24,33 @@
     android:layout_weight="1" >
 
     <android.support.v4.widget.SwipeRefreshLayout
-        android:id="@+id/swipe_refresh_files"
+        android:id="@+id/swipe_containing_list"
         android:layout_width="match_parent"
         android:layout_height="match_parent" 
         android:layout_weight="1"
-        android:footerDividersEnabled="false" > 
+        android:footerDividersEnabled="false"
+        android:visibility="visible" >
         
-        <third_parties.in.srain.cube.GridViewWithHeaderAndFooter
+        <com.owncloud.android.ui.ExtendedListView
             android:id="@+id/list_root"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:visibility="visible" />
+
+    </android.support.v4.widget.SwipeRefreshLayout>
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:id="@+id/swipe_containing_grid"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:footerDividersEnabled="false"
+        android:visibility="gone" >
+
+        <third_parties.in.srain.cube.GridViewWithHeaderAndFooter
+            android:id="@+id/grid_root"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
             android:columnWidth="100dp"
             android:gravity="center"
             android:horizontalSpacing="2dp"
@@ -42,9 +59,9 @@
             android:visibility="visible" />
 
     </android.support.v4.widget.SwipeRefreshLayout>
-    	
+
     <android.support.v4.widget.SwipeRefreshLayout
-        android:id="@+id/swipe_refresh_files_emptyView"
+        android:id="@+id/swipe_containing_empty"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="gone" >

+ 74 - 0
src/com/owncloud/android/ui/ExtendedListView.java

@@ -0,0 +1,74 @@
+/* ownCloud Android client application
+ *   Copyright (C) 2012 Bartek Przybylski
+ *   Copyright (C) 2012-2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+/**
+ * ListView allowing to specify the position of an item that should be centered in the visible area, if possible.
+ *
+ * The cleanest way I found to overcome the problem due to getHeight() returns 0 until the view is really drawn. 
+ *
+ * @author David A. Velasco
+ */
+public class ExtendedListView extends ListView {
+
+    private int mPositionToSetAndCenter = 0;
+
+    public ExtendedListView(Context context) {
+        super(context);
+    }
+
+    public ExtendedListView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ExtendedListView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     *
+     */
+    @Override
+    protected void onDraw (Canvas canvas) {
+        super.onDraw(canvas);
+        if (mPositionToSetAndCenter > 0) {
+            this.setSelectionFromTop(mPositionToSetAndCenter, getHeight() / 2);
+            mPositionToSetAndCenter = 0;
+        }
+    }
+
+    /**
+     * Public method to set the position of the item that should be centered in the visible area of the view.
+     *
+     * The position is saved here and checked in onDraw().
+     *
+     * @param position         Position (in the list of items) of the item to center in the visible area.     
+     */
+    public void setAndCenterSelection(int position) {
+        mPositionToSetAndCenter = position;
+    }
+
+}

+ 11 - 5
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -30,6 +30,7 @@ import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AbsListView;
 import android.widget.BaseAdapter;
 import android.widget.GridView;
 import android.widget.ImageView;
@@ -69,6 +70,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private FileDataStorageManager mStorageManager;
     private Account mAccount;
     private ComponentsGetter mTransferServiceGetter;
+    private boolean mGridMode;
 
     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };
 
@@ -95,6 +97,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
+
+        mGridMode = false;
     }
     
     @Override
@@ -134,8 +138,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
 
-        boolean fileView = DisplayUtils.decideViewLayout(mFiles);
-
         View view = convertView;
         OCFile file = null;
         LayoutInflater inflator = (LayoutInflater) mContext
@@ -147,7 +149,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
 
         // Find out which layout should be displayed
         ViewType viewType;
-        if (!fileView){
+        if (!mGridMode){
             viewType = ViewType.LIST_ITEM;
         } else if (file.isImage()){
             viewType = ViewType.GRID_IMAGE;
@@ -192,8 +194,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
 
                     if (!file.isFolder()) {
-                        GridView parentList = (GridView)parent;
-                        if (parentList.getChoiceMode() == GridView.CHOICE_MODE_NONE) {
+                        AbsListView parentList = (AbsListView)parent;
+                        if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {
                             checkBoxV.setVisibility(View.GONE);
                         } else {
                             if (parentList.isItemChecked(position)) {
@@ -456,4 +458,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
                 DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
     }
+
+    public void setGridMode(boolean gridMode) {
+        mGridMode = gridMode;
+    }
 }

+ 1 - 1
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -121,7 +121,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
 
                 lastModV.setVisibility(View.VISIBLE);
                 lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.lastModified()));
-                GridViewWithHeaderAndFooter parentList = (GridViewWithHeaderAndFooter)parent;
+                ListView parentList = (ListView) parent;
                 if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { 
                     checkBoxV.setVisibility(View.GONE);
                 } else {

+ 172 - 97
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -1,6 +1,6 @@
 /* ownCloud Android client application
  *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2013 ownCloud Inc.
+ *   Copyright (C) 2012-2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -20,11 +20,13 @@ package com.owncloud.android.ui.fragment;
 
 import java.util.ArrayList;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.support.v4.widget.SwipeRefreshLayout;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.GridView;
@@ -34,8 +36,11 @@ import android.widget.TextView;
 import com.actionbarsherlock.app.SherlockFragment;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
+import com.owncloud.android.ui.ExtendedListView;
 import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
+import com.owncloud.android.ui.adapter.FileListListAdapter;
+
+import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
 
 /**
  * TODO extending SherlockListFragment instead of SherlockFragment
@@ -52,7 +57,8 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
     private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL";
     private static final String KEY_EMPTY_LIST_MESSAGE = "EMPTY_LIST_MESSAGE";
 
-    private SwipeRefreshLayout mRefreshLayout;
+    private SwipeRefreshLayout mRefreshListLayout;
+    private SwipeRefreshLayout mRefreshGridLayout;
     private SwipeRefreshLayout mRefreshEmptyLayout;
     private TextView mEmptyListMessage;
     
@@ -64,40 +70,55 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     private OnEnforceableRefreshListener mOnRefreshListener = null;
     
-    protected GridViewWithHeaderAndFooter imageView;
-       
-    public void setListAdapter(ListAdapter listAdapter) {
-        imageView.setAdapter(listAdapter);
-        imageView.invalidate();
-    }
+    protected AbsListView mCurrentListView;
+    private ExtendedListView mListView;
+    private View mListFooterView;
+    private GridViewWithHeaderAndFooter mGridView;
+    private View mGridFooterView;
 
-    public GridView getGridView() {
-        return imageView;
-    }
+    private ListAdapter mAdapter;
 
-    public void setFooterView(View footer) {
-        imageView.addFooterView(footer, null, false);
-        imageView.invalidate();
-    }
 
-    public void removeFooterView(View footer) {
-        imageView.removeFooterView(footer);
-        imageView.invalidate();
+    protected void setListAdapter(ListAdapter listAdapter) {
+        mAdapter = listAdapter;
+        mCurrentListView.setAdapter(listAdapter);
+        mCurrentListView.invalidate();
     }
 
-    public int getFooterViewCount() {
-        return imageView.getFooterViewCount();
+    protected AbsListView getListView() {
+        return mCurrentListView;
     }
-    
-    protected void switchImageView(){
-       imageView.setNumColumns(GridView.AUTO_FIT);
-       imageView.invalidateRowHeight();  // Force to recalculate mRowHeight of imageView
-       imageView.invalidate();
+
+
+    protected void switchToGridView() {
+        if ((mCurrentListView == mListView)) {
+
+            mListView.setAdapter(null);
+            mRefreshListLayout.setVisibility(View.GONE);
+
+            if (mAdapter instanceof FileListListAdapter) {
+                ((FileListListAdapter) mAdapter).setGridMode(true);
+            }
+            mGridView.setAdapter(mAdapter);
+            mRefreshGridLayout.setVisibility(View.VISIBLE);
+
+            mCurrentListView = mGridView;
+        }
     }
     
-    protected void switchFileView(){
-       imageView.setNumColumns(1);
-       imageView.invalidate();
+    protected void switchToListView() {
+        if (mCurrentListView == mGridView) {
+            mGridView.setAdapter(null);
+            mRefreshGridLayout.setVisibility(View.GONE);
+
+            if (mAdapter instanceof FileListListAdapter) {
+                ((FileListListAdapter) mAdapter).setGridMode(false);
+            }
+            mListView.setAdapter(mAdapter);
+            mRefreshListLayout.setVisibility(View.VISIBLE);
+
+            mCurrentListView = mListView;
+        }
     }
     
     
@@ -106,25 +127,37 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
         Log_OC.d(TAG, "onCreateView");
 
         View v = inflater.inflate(R.layout.list_fragment, null);
-        
-        imageView = (GridViewWithHeaderAndFooter)(v.findViewById(R.id.list_root));
-        imageView.setOnItemClickListener(this);
+
+        mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
+        mListView.setOnItemClickListener(this);
+        mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
+
+        mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
+        mGridView.setNumColumns(GridView.AUTO_FIT);
+        mGridView.setOnItemClickListener(this);
+        mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         if (savedInstanceState != null) {
             int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
-            setReferencePosition(referencePosition);
+            mListView.setAndCenterSelection(referencePosition);
+            mGridView.setSelection(referencePosition);
         }
 
-        // Pull down refresh
-        mRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files);
-        mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files_emptyView);
+        // Pull-down to refresh layout
+        mRefreshListLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_list);
+        mRefreshGridLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_grid);
+        mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_containing_empty);
         mEmptyListMessage = (TextView) v.findViewById(R.id.empty_list_view);
         
-        onCreateSwipeToRefresh(mRefreshLayout);
+        onCreateSwipeToRefresh(mRefreshListLayout);
+        onCreateSwipeToRefresh(mRefreshGridLayout);
         onCreateSwipeToRefresh(mRefreshEmptyLayout);
 
-        imageView.setEmptyView(mRefreshEmptyLayout);
-        
+        mListView.setEmptyView(mRefreshEmptyLayout);
+        mGridView.setEmptyView(mRefreshEmptyLayout);
+
+        mCurrentListView = mListView;   // list as default
+
         return v;
     }
 
@@ -168,32 +201,20 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
      * reposition the visible items in the list when the device is turned to
      * other position.
      * 
-     * THe current policy is take as a reference the visible item in the center
+     * The current policy is take as a reference the visible item in the center
      * of the screen.
      * 
      * @return The position in the list of the visible item in the center of the
      *         screen.
      */
     protected int getReferencePosition() {
-        if (imageView != null) {
-            return (imageView.getFirstVisiblePosition() + imageView.getLastVisiblePosition()) / 2;
+        if (mCurrentListView != null) {
+            return (mCurrentListView.getFirstVisiblePosition() + mCurrentListView.getLastVisiblePosition()) / 2;
         } else {
             return 0;
         }
     }
 
-    /**
-     * Sets the visible part of the list from the reference position.
-     * 
-     * @param position Reference position previously returned by
-     *            {@link LocalFileListFragment#getReferencePosition()}
-     */
-    protected void setReferencePosition(int position) {
-        if (imageView != null) {
-            imageView.setSelection(position);
-        }
-    }
-
 
     /*
      * Restore index and position
@@ -203,20 +224,28 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
             // needs to be checked; not every browse-up had a browse-down before 
             
             int index = mIndexes.remove(mIndexes.size() - 1);
-            
-            int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
-            
+            final int firstPosition = mFirstPositions.remove(mFirstPositions.size() -1);
             int top = mTops.remove(mTops.size() - 1);
-            
-            imageView.smoothScrollToPosition(firstPosition);
-            
-            // Move the scroll if the selection is not visible
-            int indexPosition = mHeightCell*index;
-            int height = imageView.getHeight();
-            
-            if (indexPosition > height) {
-                imageView.smoothScrollToPosition(index);
+
+            Log_OC.d(TAG, "Setting selection to position: " + firstPosition + "; top: " + top + "; index: " + index);
+
+            if (mCurrentListView == mListView) {
+                if (mHeightCell*index <= mListView.getHeight()) {
+                    mListView.setSelectionFromTop(firstPosition, top);
+                } else {
+                    mListView.setSelectionFromTop(index, 0);
+                }
+
+            } else {
+                if (mHeightCell*index <= mGridView.getHeight()) {
+                    mGridView.setSelection(firstPosition);
+                    //mGridView.smoothScrollToPosition(firstPosition);
+                } else {
+                    mGridView.setSelection(index);
+                    //mGridView.smoothScrollToPosition(index);
+                }
             }
+
         }
     }
     
@@ -227,10 +256,10 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
         
         mIndexes.add(index);
         
-        int firstPosition = imageView.getFirstVisiblePosition();
+        int firstPosition = mCurrentListView.getFirstVisiblePosition();
         mFirstPositions.add(firstPosition);
         
-        View view = imageView.getChildAt(0);
+        View view = mCurrentListView.getChildAt(0);
         int top = (view == null) ? 0 : view.getTop() ;
 
         mTops.add(top);
@@ -247,10 +276,10 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     @Override
     public void onRefresh() {
-        // to be @overriden
-        mRefreshLayout.setRefreshing(false);
+        mRefreshListLayout.setRefreshing(false);
+        mRefreshGridLayout.setRefreshing(false);
         mRefreshEmptyLayout.setRefreshing(false);
-        
+
         if (mOnRefreshListener != null) {
             mOnRefreshListener.onRefresh();
         }
@@ -261,32 +290,18 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
     
 
     /**
-     * Enables swipe gesture
-     */
-    public void enableSwipe() {
-        mRefreshLayout.setEnabled(true);
-    }
- 
-    /**
-     * Disables swipe gesture. It prevents manual gestures but keeps the option you show
-     * refreshing programmatically.
+     * Disables swipe gesture.
+     *
+     * Sets the 'enabled' state of the refresh layouts contained in the fragment.
+     *
+     * When 'false' is set, prevents user gestures but keeps the option to refresh programatically,
+     *
+     * @param   enabled     Desired state for capturing swipe gesture.
      */
-    public void disableSwipe() {
-        mRefreshLayout.setEnabled(false);
-    }
-    
-    /**
-     * It shows the SwipeRefreshLayout progress
-     */
-    public void showSwipeProgress() {
-        mRefreshLayout.setRefreshing(true);
-    }
- 
-    /**
-     * It shows the SwipeRefreshLayout progress
-     */
-    public void hideSwipeProgress() {
-        mRefreshLayout.setRefreshing(false);
+    public void setSwipeEnabled(boolean enabled) {
+        mRefreshListLayout.setEnabled(enabled);
+        mRefreshGridLayout.setEnabled(enabled);
+        mRefreshEmptyLayout.setEnabled(enabled);
     }
 
     /**
@@ -317,11 +332,71 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
 
     @Override
     public void onRefresh(boolean ignoreETag) {
-        mRefreshLayout.setRefreshing(false);
+        mRefreshListLayout.setRefreshing(false);
+        mRefreshGridLayout.setRefreshing(false);
         mRefreshEmptyLayout.setRefreshing(false);
 
         if (mOnRefreshListener != null) {
             mOnRefreshListener.onRefresh(ignoreETag);
         }
     }
+
+
+    protected void setChoiceMode(int choiceMode) {
+        mListView.setChoiceMode(choiceMode);
+        mGridView.setChoiceMode(choiceMode);
+    }
+
+    protected void registerForContextMenu() {
+        registerForContextMenu(mListView);
+        registerForContextMenu(mGridView);
+        mListView.setOnCreateContextMenuListener(this);
+        mGridView.setOnCreateContextMenuListener(this);
+    }
+
+    /**
+     * TODO doc
+     * To be called before setAdapter, or GridViewWithHeaderAndFooter will throw an exception
+     *
+     * @param enabled
+     */
+    protected void setFooterEnabled(boolean enabled) {
+        if (enabled) {
+            if (mGridView.getFooterViewCount() == 0) {
+                if (mGridFooterView.getParent() != null ) {
+                    ((ViewGroup) mGridFooterView.getParent()).removeView(mGridFooterView);
+                }
+                mGridView.addFooterView(mGridFooterView, null, false);
+            }
+            mGridFooterView.invalidate();
+
+            if (mListView.getFooterViewsCount() == 0) {
+                if (mListFooterView.getParent() != null ) {
+                    ((ViewGroup) mListFooterView.getParent()).removeView(mListFooterView);
+                }
+                mListView.addFooterView(mListFooterView, null, false);
+            }
+            mListFooterView.invalidate();
+
+        } else {
+            mGridView.removeFooterView(mGridFooterView);
+            mListView.removeFooterView(mListFooterView);
+        }
+    }
+
+    /**
+     * TODO doc
+     * @param text
+     */
+    protected void setFooterText(String text) {
+        if (text != null && text.length() > 0) {
+            ((TextView)mListFooterView.findViewById(R.id.footerText)).setText(text);
+            ((TextView)mGridFooterView.findViewById(R.id.footerText)).setText(text);
+            setFooterEnabled(true);
+
+        } else {
+            setFooterEnabled(false);
+        }
+    }
+
 }

+ 9 - 9
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -76,12 +76,12 @@ public class LocalFileListFragment extends ExtendedListFragment {
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         Log_OC.i(TAG, "onCreateView() start");
         View v = super.onCreateView(inflater, container, savedInstanceState);
-        getGridView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-        disableSwipe(); // Disable pull refresh
+        setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+        setSwipeEnabled(false); // Disable pull-to-refresh
         setMessageForEmptyList(getString(R.string.local_file_list_empty));
         Log_OC.i(TAG, "onCreateView() end");
         return v;
-    }    
+    }
 
 
     /**
@@ -117,7 +117,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
             } else {    /// Click on a file
                 ImageView checkBoxV = (ImageView) v.findViewById(R.id.custom_checkbox);
                 if (checkBoxV != null) {
-                    if (getGridView().isItemChecked(position)) {
+                    if (getListView().isItemChecked(position)) {
                         checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
                     } else {
                         checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
@@ -194,10 +194,10 @@ public class LocalFileListFragment extends ExtendedListFragment {
             directory = directory.getParentFile();
         }
 
-        imageView.clearChoices();   // by now, only files in the same directory will be kept as selected
+        mCurrentListView.clearChoices();   // by now, only files in the same directory will be kept as selected
         mAdapter.swapDirectory(directory);
         if (mDirectory == null || !mDirectory.equals(directory)) {
-            imageView.setSelection(0);
+            mCurrentListView.setSelection(0);
         }
         mDirectory = directory;
     }
@@ -210,11 +210,11 @@ public class LocalFileListFragment extends ExtendedListFragment {
      */
     public String[] getCheckedFilePaths() {
         ArrayList<String> result = new ArrayList<String>();
-        SparseBooleanArray positions = imageView.getCheckedItemPositions();
+        SparseBooleanArray positions = mCurrentListView.getCheckedItemPositions();
         if (positions.size() > 0) {
             for (int i = 0; i < positions.size(); i++) {
                 if (positions.get(positions.keyAt(i)) == true) {
-                    result.add(((File) imageView.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
+                    result.add(((File) mCurrentListView.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
                 }
             }
 
@@ -234,7 +234,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
         /**
          * Callback method invoked when a directory is clicked by the user on the files list
          *  
-         * @param file
+         * @param directory
          */
         public void onDirectoryClick(File directory);
         

+ 45 - 59
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -18,10 +18,8 @@
 package com.owncloud.android.ui.fragment;
 
 import java.io.File;
-import java.util.Vector;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.widget.SwipeRefreshLayout;
@@ -29,11 +27,8 @@ import android.view.ContextMenu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.TextView;
-import android.view.LayoutInflater;
 
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -49,7 +44,6 @@ import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
 import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewMediaFragment;
-import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 
 /**
@@ -73,11 +67,12 @@ public class OCFileListFragment extends ExtendedListFragment {
             
     private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
 
+    private final static Double THUMBNAIL_THRESHOLD = 0.5;
+
     private FileFragment.ContainerActivity mContainerActivity;
    
     private OCFile mFile = null;
     private FileListListAdapter mAdapter;
-    private View mFooterView;
     private boolean mJustFolders;
     
     private OCFile mTargetFile;
@@ -126,12 +121,10 @@ public class OCFileListFragment extends ExtendedListFragment {
             mFile = savedInstanceState.getParcelable(KEY_FILE);
         }
 
-        mFooterView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
-                R.layout.list_footer, null, false);
         if (mJustFolders) {
-            removeFooterView(mFooterView);
+            setFooterEnabled(false);
         } else {
-            setFooterView(mFooterView);
+            setFooterEnabled(true);
         }
 
         Bundle args = getArguments();
@@ -142,11 +135,10 @@ public class OCFileListFragment extends ExtendedListFragment {
                 mContainerActivity
                 );
         setListAdapter(mAdapter);
-        
-        registerForContextMenu(getGridView());
-        getGridView().setOnCreateContextMenuListener(this);
+
+        registerForContextMenu();
   }
-    
+
     /**
      * Saves the current listed folder.
      */
@@ -396,71 +388,65 @@ public class OCFileListFragment extends ExtendedListFragment {
 
             mAdapter.swapDirectory(directory, storageManager);
             if (mFile == null || !mFile.equals(directory)) {
-                imageView.setSelection(0);
+                mCurrentListView.setSelection(0);
             }
             mFile = directory;
 
-            Vector<OCFile> files = storageManager.getFolderContent(directory);
-            // Update Footer
-            TextView footerText = (TextView) mFooterView.findViewById(R.id.footerText);
-            footerText.setText(generateFooterText(directory));
-            if (DisplayUtils.decideViewLayout(files) && !mJustFolders){
-                switchImageView();
-            } else {
-                switchFileView();
-            }
+            updateLayout();
+
         }
     }
-    
-    private String generateFooterText(OCFile directory) {
-        Integer files = 0;
-        Integer folders = 0;
 
-        FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-        Vector<OCFile> mFiles = storageManager.getFolderContent(mFile);
+    private void updateLayout() {
+        if (!mJustFolders) {
+            int filesCount = 0, foldersCount = 0, imagesCount = 0;
+            int count = mAdapter.getCount();
+            OCFile file;
+            for (int i=0; i < count ; i++) {
+                file = (OCFile) mAdapter.getItem(i);
+                if (file.isFolder()) {
+                    foldersCount++;
+                } else {
+                    filesCount++;
+                    if (file.isImage()){
+                        imagesCount++;
+                    }
+                }
+            }
+            // set footer text
+            setFooterText(generateFooterText(filesCount, foldersCount));
 
-        for (OCFile ocFile : mFiles) {
-            if (ocFile.isFolder()) {
-                folders++;
+            // decide grid vs list view
+            if (((double)imagesCount / (double)filesCount) >= THUMBNAIL_THRESHOLD) {
+                switchToGridView();
             } else {
-                files++;
+                switchToListView();
             }
         }
+    }
 
+    private String generateFooterText(int filesCount, int foldersCount) {
         String output = "";
-       
-        if (files > 0){
-            if (files == 1) {
-                output = output + files.toString() + " " + getResources().getString(R.string.file_list_file);
+        if (filesCount > 0){
+            if (filesCount == 1) {
+                output = output + filesCount + " " + getResources().getString(R.string.file_list_file);
             } else {
-                output = output + files.toString() + " " + getResources().getString(R.string.file_list_files);
+                output = output + filesCount + " " + getResources().getString(R.string.file_list_files);
             }
         }
-        if (folders > 0 && files > 0){
+        if (foldersCount > 0 && filesCount > 0){
             output = output + ", ";
         }
-        if (folders == 1) {
-            output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folder);
-        } else if (folders > 1) {
-            output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folders);
+        if (foldersCount == 1) {
+            output = output + foldersCount + " " + getResources().getString(R.string.file_list_folder);
+        } else if (foldersCount > 1) {
+            output = output + foldersCount + " " + getResources().getString(R.string.file_list_folders);
         }
 
-        // Fix for showing or not to show the footerView
-        if (mJustFolders || (folders == 0 && files == 0)) {
-                // If fragment to choose target folder for a MOVE or
-                // no files or folders,
-                // remove footerView for allowing to show the emptyList message
-            removeFooterView(mFooterView);
-        } else { // set a new footerView if there is not one for showing the number or files/folders
-            if (getFooterViewCount()== 0) {
-                ((ViewGroup)mFooterView.getParent()).removeView(mFooterView);
-                setFooterView(mFooterView);
-            }
-        }
-        
         return output;
     }
-    
+
+
     public void sortByName(boolean descending) {
         mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
     }

+ 0 - 28
src/com/owncloud/android/utils/DisplayUtils.java

@@ -52,8 +52,6 @@ public class DisplayUtils {
     
     private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
 
-    private final static Double THUMBNAIL_THRESHOLD = 0.5;
-
     private static HashMap<String, String> mimeType2HUmanReadable;
     static {
         mimeType2HUmanReadable = new HashMap<String, String>();
@@ -344,30 +342,4 @@ public class DisplayUtils {
         return path;
     }
 
-    /**
-     *
-     * @param mFiles
-     * @return true: imageView, false: listView
-     */
-    public static boolean decideViewLayout(Vector<OCFile> mFiles){
-        // decide image vs. file view
-        double countImages = 0;
-        double countFiles = 0;
-
-        for (OCFile file : mFiles){
-            if (!file.isFolder()){
-                countFiles++;
-
-                if (file.isImage()){
-                    countImages++;
-                }
-            }
-        }
-
-        if ((countImages / countFiles) >= THUMBNAIL_THRESHOLD){
-            return true;
-        } else {
-            return false;
-        }
-    }
 }

+ 73 - 19
src/third_parties/in/srain/cube/GridViewWithHeaderAndFooter.java

@@ -17,22 +17,28 @@
 package third_parties.in.srain.cube;
 
 
-        import android.annotation.TargetApi;
-        import android.content.Context;
-        import android.database.DataSetObservable;
-        import android.database.DataSetObserver;
-        import android.os.Build;
-        import android.util.AttributeSet;
-        import android.util.Log;
-        import android.view.View;
-        import android.view.ViewGroup;
-        import android.widget.*;
-
-        import java.lang.reflect.Field;
-        import java.util.ArrayList;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.database.DataSetObservable;
+import android.database.DataSetObserver;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.FrameLayout;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+import android.widget.WrapperListAdapter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
 
 /**
- * A {@link GridView} that supports adding header rows in a
+ * A {@link android.widget.GridView} that supports adding header rows in a
  * very similar way to {@link android.widget.ListView}.
  * See {@link GridViewWithHeaderAndFooter#addHeaderView(View, Object, boolean)}
  * See {@link GridViewWithHeaderAndFooter#addFooterView(View, Object, boolean)}
@@ -52,7 +58,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
         public View view;
         public ViewGroup viewContainer;
         /**
-         * The data backing the view. This is returned from {@link ListAdapter#getItem(int)}.
+         * The data backing the view. This is returned from {@link android.widget.ListAdapter#getItem(int)}.
          */
         public Object data;
         /**
@@ -151,7 +157,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
 
         if (lyp != null) {
             v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
-            fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
+            fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));
         }
         fl.addView(v);
         info.view = v;
@@ -184,7 +190,7 @@ public class GridViewWithHeaderAndFooter extends GridView {
 
         if (lyp != null) {
             v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
-            fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
+            fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));
         }
         fl.addView(v);
         info.view = v;
@@ -315,9 +321,9 @@ public class GridViewWithHeaderAndFooter extends GridView {
         }
         int mColumnWidth = getColumnWidthCompatible();
         View view = getAdapter().getView(numColumns * mHeaderViewInfos.size(), mViewForMeasureRowHeight, this);
-        AbsListView.LayoutParams p = (AbsListView.LayoutParams) view.getLayoutParams();
+        LayoutParams p = (LayoutParams) view.getLayoutParams();
         if (p == null) {
-            p = new AbsListView.LayoutParams(-1, -2, 0);
+            p = new LayoutParams(-1, -2, 0);
             view.setLayoutParams(p);
         }
         int childHeightSpec = getChildMeasureSpec(
@@ -784,4 +790,52 @@ public class GridViewWithHeaderAndFooter extends GridView {
             mDataSetObservable.notifyChanged();
         }
     }
+
+
+    /**
+     * Sets the selected item and positions the selection y pixels from the top edge of the ListView.
+     * (If in touch mode, the item will not be selected but it will still be positioned appropriately.)
+     *
+     * @param position     Index (starting at 0) of the data item to be selected.
+     * @param y            The distance from the top edge of the ListView (plus padding)
+     *                     that the item will be positioned.
+     *
+     * @see <a href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/widget/ListView.java#ListView.setSelectionFromTop%28int%2Cint%29">Original code</a>
+     */
+    public void setSelectionFromTop(int position, int y) {
+        if (getAdapter() == null) {
+            return;
+        }
+
+        setSelection(position);
+        //setSelectionInt(position);
+
+        /*if (!isInTouchMode()) {
+            position = super.lookForSelectablePosition(position, true);
+            if (position >= 0) {
+                setNextSelectedPositionInt(position);
+            }
+        } else {
+            mResurrectToPosition = position;
+        }*/
+
+        /*
+        if (position >= 0) {
+            mLayoutMode = LAYOUT_SPECIFIC;
+            mSpecificTop = mListPadding.top + y;
+
+            if (mNeedSync) {
+                mSyncPosition = position;
+                mSyncRowId = getAdapter().getItemId(position);
+            }
+
+            if (mPositionScroller != null) {
+                mPositionScroller.stop();
+            }
+
+            requestLayout();
+        }
+        */
+    }
+
 }