Jelajahi Sumber

Merge pull request #5992 from nextcloud/newDesign-sort-gridswitch

New design (UI) - Sort and Gridview switch Bar
Andy Scherzinger 5 tahun lalu
induk
melakukan
4a764ff616

+ 3 - 8
src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -152,6 +152,7 @@ import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 
 import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
 
 /**
  * Displays, what files the user has available in his ownCloud. This is the main view.
@@ -868,14 +869,8 @@ public class FileDisplayActivity extends FileActivity
                 break;
             }
             case R.id.action_sort: {
-                FragmentManager fm = getSupportFragmentManager();
-                FragmentTransaction ft = fm.beginTransaction();
-                ft.addToBackStack(null);
-
-                SortingOrderDialogFragment mSortingOrderDialogFragment = SortingOrderDialogFragment.newInstance(
-                    preferences.getSortOrderByFolder(getListOfFilesFragment().getCurrentFile()));
-                mSortingOrderDialogFragment.show(ft, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
-
+                openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                               preferences.getSortOrderByFolder(getListOfFilesFragment().getCurrentFile()));
                 break;
             }
             case R.id.action_switch_view: {

+ 4 - 8
src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java

@@ -72,6 +72,8 @@ import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
+
 public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity,
     OnClickListener,
     OnEnforceableRefreshListener,
@@ -324,14 +326,8 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
                 break;
             }
             case R.id.action_sort: {
-                FragmentManager fm = getSupportFragmentManager();
-                FragmentTransaction ft = fm.beginTransaction();
-                ft.addToBackStack(null);
-
-                SortingOrderDialogFragment mSortingOrderDialogFragment = SortingOrderDialogFragment.newInstance(
-                    preferences.getSortOrderByFolder(getListOfFilesFragment().getCurrentFile()));
-                mSortingOrderDialogFragment.show(ft, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
-
+                openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                               preferences.getSortOrderByFolder(getListOfFilesFragment().getCurrentFile()));
                 break;
             }
             default:

+ 4 - 5
src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

@@ -39,7 +39,6 @@ import android.content.res.Resources.NotFoundException;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -124,6 +123,8 @@ import androidx.core.view.MenuItemCompat;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.FragmentManager;
 
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
+
 /**
  * This can be used to upload things to an ownCloud instance.
  */
@@ -1053,10 +1054,8 @@ public class ReceiveExternalFilesActivity extends FileActivity
                 showAccountChooserDialog();
                 break;
             case R.id.action_sort:
-                SortingOrderDialogFragment mSortingOrderDialogFragment = SortingOrderDialogFragment.newInstance(
-                    preferences.getSortOrderByFolder(mFile));
-                mSortingOrderDialogFragment.show(getSupportFragmentManager(),
-                        SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
+                openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                               preferences.getSortOrderByFolder(mFile));
                 break;
             default:
                 retval = super.onOptionsItemSelected(item);

+ 0 - 1
src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

@@ -70,7 +70,6 @@ import com.owncloud.android.ui.decoration.MediaGridItemDecoration;
 import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment;
 import com.owncloud.android.ui.dialog.parcel.SyncedFolderParcelable;
 import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.FilesSyncHelper;
 import com.owncloud.android.utils.PermissionUtil;
 import com.owncloud.android.utils.ThemeUtils;
 

+ 4 - 9
src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -74,6 +74,8 @@ import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
 
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
+
 /**
  * Displays local files and let the user choose what of them wants to upload
  * to the current ownCloud account.
@@ -83,7 +85,6 @@ public class UploadFilesActivity extends FileActivity implements
     OnClickListener, ConfirmationDialogFragmentListener, SortingOrderDialogFragment.OnSortingOrderListener,
     CheckAvailableSpaceTask.CheckAvailableSpaceListener, StoragePathAdapter.StoragePathAdapterListener, Injectable {
 
-    private static final String SORT_ORDER_DIALOG_TAG = "SORT_ORDER_DIALOG";
     private static final int SINGLE_DIR = 1;
 
     private ArrayAdapter<String> mDirectories;
@@ -296,14 +297,8 @@ public class UploadFilesActivity extends FileActivity implements
                 break;
             }
             case R.id.action_sort: {
-                FragmentManager fm = getSupportFragmentManager();
-                FragmentTransaction ft = fm.beginTransaction();
-                ft.addToBackStack(null);
-
-                SortingOrderDialogFragment mSortingOrderDialogFragment = SortingOrderDialogFragment.newInstance(
-                    preferences.getSortOrderByType(FileSortOrder.Type.uploadFilesView));
-                mSortingOrderDialogFragment.show(ft, SORT_ORDER_DIALOG_TAG);
-
+                openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                               preferences.getSortOrderByType(FileSortOrder.Type.uploadFilesView));
                 break;
             }
             case R.id.action_switch_view: {

+ 6 - 0
src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -54,6 +54,7 @@ import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.google.android.material.button.MaterialButton;
 import com.google.android.material.floatingactionbutton.FloatingActionButton;
 import com.nextcloud.client.account.UserAccountManager;
 import com.nextcloud.client.di.Injectable;
@@ -118,6 +119,8 @@ public class ExtendedListFragment extends Fragment implements
     @Inject UserAccountManager accountManager;
     private ScaleGestureDetector mScaleGestureDetector;
     protected SwipeRefreshLayout mRefreshListLayout;
+    protected MaterialButton mSortButton;
+    protected MaterialButton mSwitchGridViewButton;
     protected LinearLayout mEmptyListContainer;
     protected TextView mEmptyListMessage;
     protected TextView mEmptyListHeadline;
@@ -374,6 +377,9 @@ public class ExtendedListFragment extends Fragment implements
         ThemeUtils.colorSwipeRefreshLayout(getContext(), mRefreshListLayout);
         mRefreshListLayout.setOnRefreshListener(this);
 
+        mSortButton = v.findViewById(R.id.sort_button);
+        mSwitchGridViewButton = v.findViewById(R.id.switch_grid_view_button);
+
         mFabMain = v.findViewById(R.id.fab_main);
         ThemeUtils.tintFloatingActionButton(mFabMain, R.drawable.ic_plus, getContext());
 

+ 71 - 7
src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -28,6 +28,7 @@ import android.accounts.Account;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
@@ -120,6 +121,7 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.appcompat.app.ActionBar;
+import androidx.core.content.ContextCompat;
 import androidx.drawerlayout.widget.DrawerLayout;
 import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.GridLayoutManager;
@@ -128,6 +130,13 @@ import androidx.recyclerview.widget.RecyclerView;
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
 import static com.owncloud.android.datamodel.OCFile.ROOT_PATH;
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
+import static com.owncloud.android.utils.FileSortOrder.sort_a_to_z_id;
+import static com.owncloud.android.utils.FileSortOrder.sort_big_to_small_id;
+import static com.owncloud.android.utils.FileSortOrder.sort_new_to_old_id;
+import static com.owncloud.android.utils.FileSortOrder.sort_old_to_new_id;
+import static com.owncloud.android.utils.FileSortOrder.sort_small_to_big_id;
+import static com.owncloud.android.utils.FileSortOrder.sort_z_to_a_id;
 
 /**
  * A Fragment that lists all files and folders in a given path.
@@ -352,9 +361,17 @@ public class OCFileListFragment extends ExtendedListFragment implements
         }
         prepareCurrentSearch(searchEvent);
 
-        if (isGridViewPreferred(getCurrentFile())) {
-            switchToGridView();
-        }
+        mSortButton.setOnClickListener(v -> openSortingOrderDialogFragment(requireFragmentManager(),
+                                                                           preferences.getSortOrderByFolder(mFile)));
+
+        mSwitchGridViewButton.setOnClickListener(v -> {
+            if (isGridEnabled()) {
+                setListAsPreferred();
+            } else {
+                setGridAsPreferred();
+            }
+            setGridSwitchButton();
+        });
 
         setTitle();
 
@@ -747,12 +764,11 @@ public class OCFileListFragment extends ExtendedListFragment implements
 
     @Override
     public void onPrepareOptionsMenu(@NonNull Menu menu) {
-        Menu mMenu = menu;
 
         if (mOriginalMenuItems.size() == 0) {
-            mOriginalMenuItems.add(mMenu.findItem(R.id.action_switch_view));
-            mOriginalMenuItems.add(mMenu.findItem(R.id.action_sort));
-            mOriginalMenuItems.add(mMenu.findItem(R.id.action_search));
+            mOriginalMenuItems.add(menu.findItem(R.id.action_switch_view));
+            mOriginalMenuItems.add(menu.findItem(R.id.action_sort));
+            mOriginalMenuItems.add(menu.findItem(R.id.action_search));
         }
 
         changeGridIcon(menu);   // this is enough if the option stays out of the action bar
@@ -765,6 +781,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
                 menu.add(menuItemOrig.getGroupId(), menuItemOrig.getItemId(), menuItemOrig.getOrder(),
                          menuItemOrig.getTitle());
             }
+            mSortButton.setVisibility(View.VISIBLE);
 
         } else if (menuItemAddRemoveValue == MenuItemAddRemove.ADD_GRID_AND_SORT) {
             if (menu.findItem(R.id.action_switch_view) == null) {
@@ -772,12 +789,14 @@ public class OCFileListFragment extends ExtendedListFragment implements
                 menu.add(menuItemOrig.getGroupId(), menuItemOrig.getItemId(), menuItemOrig.getOrder(),
                          menuItemOrig.getTitle());
             }
+            mSwitchGridViewButton.setVisibility(View.VISIBLE);
 
             if (menu.findItem(R.id.action_sort) == null) {
                 menuItemOrig = mOriginalMenuItems.get(1);
                 menu.add(menuItemOrig.getGroupId(), menuItemOrig.getItemId(), menuItemOrig.getOrder(),
                          menuItemOrig.getTitle());
             }
+            mSortButton.setVisibility(View.VISIBLE);
         } else if (menuItemAddRemoveValue == MenuItemAddRemove.REMOVE_SEARCH) {
             menu.removeItem(R.id.action_search);
         } else if (menuItemAddRemoveValue == MenuItemAddRemove.ADD_GRID_AND_SORT_WITH_SEARCH) {
@@ -786,12 +805,14 @@ public class OCFileListFragment extends ExtendedListFragment implements
                 menu.add(menuItemOrig.getGroupId(), menuItemOrig.getItemId(), menuItemOrig.getOrder(),
                          menuItemOrig.getTitle());
             }
+            mSwitchGridViewButton.setVisibility(View.VISIBLE);
 
             if (menu.findItem(R.id.action_sort) == null) {
                 menuItemOrig = mOriginalMenuItems.get(1);
                 menu.add(menuItemOrig.getGroupId(), menuItemOrig.getItemId(), menuItemOrig.getOrder(),
                          menuItemOrig.getTitle());
             }
+            mSortButton.setVisibility(View.VISIBLE);
 
             if (menu.findItem(R.id.action_search) == null) {
                 menuItemOrig = mOriginalMenuItems.get(2);
@@ -801,10 +822,13 @@ public class OCFileListFragment extends ExtendedListFragment implements
         } else if (menuItemAddRemoveValue == MenuItemAddRemove.REMOVE_SORT) {
             menu.removeItem(R.id.action_sort);
             menu.removeItem(R.id.action_search);
+            mSortButton.setVisibility(View.GONE);
         } else if (menuItemAddRemoveValue == MenuItemAddRemove.REMOVE_GRID_AND_SORT) {
             menu.removeItem(R.id.action_sort);
             menu.removeItem(R.id.action_switch_view);
             menu.removeItem(R.id.action_search);
+            mSortButton.setVisibility(View.GONE);
+            mSwitchGridViewButton.setVisibility(View.GONE);
         }
     }
 
@@ -1272,6 +1296,9 @@ public class OCFileListFragment extends ExtendedListFragment implements
             switchToListView();
         }
 
+        setSortButton(preferences.getSortOrderByFolder(mFile));
+        setGridSwitchButton();
+
         if (mHideFab) {
             setFabVisible(false);
         } else {
@@ -1293,9 +1320,46 @@ public class OCFileListFragment extends ExtendedListFragment implements
 
 
     public void sortFiles(FileSortOrder sortOrder) {
+        setSortButton(sortOrder);
         mAdapter.setSortOrder(mFile, sortOrder);
     }
 
+    private void setSortButton(FileSortOrder sortOrder) {
+        int nameId;
+        switch (sortOrder.name) {
+            case sort_z_to_a_id:
+                nameId = R.string.menu_item_sort_by_name_z_a;
+                break;
+            case sort_new_to_old_id:
+                nameId = R.string.menu_item_sort_by_date_newest_first;
+                break;
+            case sort_old_to_new_id:
+                nameId = R.string.menu_item_sort_by_date_oldest_first;
+                break;
+            case sort_big_to_small_id:
+                nameId = R.string.menu_item_sort_by_size_biggest_first;
+                break;
+            case sort_small_to_big_id:
+                nameId = R.string.menu_item_sort_by_size_smallest_first;
+                break;
+            case sort_a_to_z_id:
+            default:
+                nameId = R.string.menu_item_sort_by_name_a_z;
+                break;
+        }
+        mSortButton.setText(getString(nameId));
+    }
+
+    private void setGridSwitchButton() {
+        if (isGridEnabled()) {
+            mSwitchGridViewButton.setContentDescription(getString(R.string.action_switch_list_view));
+            mSwitchGridViewButton.setIcon(ContextCompat.getDrawable(requireContext(), R.drawable.ic_view_list));
+        } else {
+            mSwitchGridViewButton.setContentDescription(getString(R.string.action_switch_grid_view));
+            mSwitchGridViewButton.setIcon(ContextCompat.getDrawable(requireContext(), R.drawable.ic_view_module));
+        }
+    }
+
     /**
      * Determines if user set folder to grid or list view. If folder is not set itself,
      * it finds a parent that is set (at least root is set).

+ 5 - 8
src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java

@@ -63,6 +63,8 @@ import butterknife.BindView;
 import butterknife.ButterKnife;
 import butterknife.Unbinder;
 
+import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
+
 /**
  * Presenting trashbin data, received from presenter
  */
@@ -177,14 +179,9 @@ public class TrashbinActivity extends FileActivity implements
                 }
                 break;
             case R.id.action_sort: {
-                FragmentManager fm = getSupportFragmentManager();
-                FragmentTransaction ft = fm.beginTransaction();
-                ft.addToBackStack(null);
-
-                SortingOrderDialogFragment mSortingOrderDialogFragment = SortingOrderDialogFragment.newInstance(
-                    preferences.getSortOrderByType(FileSortOrder.Type.trashBinView, FileSortOrder.sort_new_to_old));
-                mSortingOrderDialogFragment.show(ft, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
-
+                openSortingOrderDialogFragment(getSupportFragmentManager(),
+                                               preferences.getSortOrderByType(FileSortOrder.Type.trashBinView,
+                                                                              FileSortOrder.sort_new_to_old));
                 break;
             }
             case R.id.action_empty_trashbin:

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

@@ -69,6 +69,7 @@ import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.TextDrawable;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
 import com.owncloud.android.ui.events.SearchEvent;
 import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.utils.glide.CustomGlideUriLoader;
@@ -97,6 +98,10 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 import androidx.appcompat.widget.AppCompatDrawableManager;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+import static com.owncloud.android.ui.dialog.SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT;
 
 /**
  * A helper class for UI/display related operations.
@@ -740,4 +745,11 @@ public final class DisplayUtils {
         Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
         activity.finish();
     }
+
+    static public void openSortingOrderDialogFragment(FragmentManager supportFragmentManager, FileSortOrder sortOrder) {
+        FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
+        fragmentTransaction.addToBackStack(null);
+
+        SortingOrderDialogFragment.newInstance(sortOrder).show(fragmentTransaction, SORTING_ORDER_FRAGMENT);
+    }
 }

+ 13 - 7
src/main/java/com/owncloud/android/utils/FileSortOrder.java

@@ -34,18 +34,24 @@ import java.util.Map;
  */
 
 public class FileSortOrder {
-    public static final FileSortOrder sort_a_to_z = new FileSortOrderByName("sort_a_to_z", true);
-    public static final FileSortOrder sort_z_to_a = new FileSortOrderByName("sort_z_to_a", false);
-    public static final FileSortOrder sort_old_to_new = new FileSortOrderByDate("sort_old_to_new", true);
-    public static final FileSortOrder sort_new_to_old = new FileSortOrderByDate("sort_new_to_old", false);
-    public static final FileSortOrder sort_small_to_big = new FileSortOrderBySize("sort_small_to_big", true);
-    public static final FileSortOrder sort_big_to_small = new FileSortOrderBySize("sort_big_to_small", false);
+    public static final String sort_a_to_z_id = "sort_a_to_z";
+    public static final String sort_z_to_a_id = "sort_z_to_a";
+    public static final String sort_old_to_new_id = "sort_old_to_new";
+    public static final String sort_new_to_old_id = "sort_new_to_old";
+    public static final String sort_small_to_big_id = "sort_small_to_big";
+    public static final String sort_big_to_small_id = "sort_big_to_small";
+
+    public static final FileSortOrder sort_a_to_z = new FileSortOrderByName(sort_a_to_z_id, true);
+    public static final FileSortOrder sort_z_to_a = new FileSortOrderByName(sort_z_to_a_id, false);
+    public static final FileSortOrder sort_old_to_new = new FileSortOrderByDate(sort_old_to_new_id, true);
+    public static final FileSortOrder sort_new_to_old = new FileSortOrderByDate(sort_new_to_old_id, false);
+    public static final FileSortOrder sort_small_to_big = new FileSortOrderBySize(sort_small_to_big_id, true);
+    public static final FileSortOrder sort_big_to_small = new FileSortOrderBySize(sort_big_to_small_id, false);
 
     public static final Map<String, FileSortOrder> sortOrders;
 
     public enum Type {
         trashBinView, localFileListView, uploadFilesView
-
     }
     static {
         sortOrders = new HashMap<>();

+ 9 - 0
src/main/res/drawable/ic_keyboard_arrow_down.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z"/>
+</vector>

+ 24 - 26
src/main/res/layout/files.xml

@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   ownCloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
@@ -21,8 +20,8 @@
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:fitsSystemWindows="true"
-    android:clickable="true" >
+    android:clickable="true"
+    android:fitsSystemWindows="true">
 
     <!-- The main content view -->
     <LinearLayout
@@ -31,30 +30,29 @@
         android:id="@+id/root_layout"
         android:orientation="vertical">
 
-        <include
-            layout="@layout/toolbar_standard" />
+            <include layout="@layout/toolbar_standard" />
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:background="@color/bg_default"
-            android:baselineAligned="false"
-            android:orientation="horizontal"
-            android:id="@+id/ListLayout"
-            android:contentDescription="@string/list_layout">
-
-            <FrameLayout
-                android:id="@+id/left_fragment_container"
-                android:layout_width="@dimen/zero"
+            <LinearLayout
+                android:id="@+id/ListLayout"
+                android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:layout_weight="1" />
+                android:background="@color/bg_default"
+                android:baselineAligned="false"
+                android:contentDescription="@string/list_layout"
+                android:orientation="horizontal">
 
-            <FrameLayout
-                android:id="@+id/right_fragment_container"
-                android:layout_width="@dimen/zero"
-                android:layout_height="match_parent"
-                android:layout_weight="2" />
-        </LinearLayout>
+                <FrameLayout
+                    android:id="@+id/left_fragment_container"
+                    android:layout_width="@dimen/zero"
+                    android:layout_height="match_parent"
+                    android:layout_weight="1" />
+
+                <FrameLayout
+                    android:id="@+id/right_fragment_container"
+                    android:layout_width="@dimen/zero"
+                    android:layout_height="match_parent"
+                    android:layout_weight="2" />
+            </LinearLayout>
 
     </LinearLayout>
 
@@ -62,6 +60,6 @@
         layout="@layout/drawer"
         android:layout_width="@dimen/drawer_width"
         android:layout_height="match_parent"
-        android:layout_gravity="start"/>
+        android:layout_gravity="start" />
 
 </androidx.drawerlayout.widget.DrawerLayout>

+ 66 - 17
src/main/res/layout/list_fragment.xml

@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
   ownCloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
@@ -18,6 +17,7 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
@@ -26,32 +26,81 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
+        <com.google.android.material.appbar.AppBarLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/bg_default"
+            app:elevation="0dp">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                app:layout_scrollFlags="scroll|enterAlways|snap">
+
+                <com.google.android.material.button.MaterialButton
+                    android:id="@+id/sort_button"
+                    style="@style/Widget.MaterialComponents.Button.TextButton"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginStart="8dp"
+                    android:contentDescription="@string/actionbar_sort"
+                    android:minWidth="0dp"
+                    android:text="@string/menu_item_sort_by_date_newest_first"
+                    android:textAlignment="textStart"
+                    android:textAllCaps="false"
+                    android:textColor="@color/fontAppbar"
+                    android:textSize="14sp"
+                    app:icon="@drawable/ic_keyboard_arrow_down"
+                    app:iconGravity="textEnd"
+                    app:iconSize="16dp"
+                    app:iconTint="@color/fontAppbar"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <com.google.android.material.button.MaterialButton
+                    android:id="@+id/switch_grid_view_button"
+                    style="@style/Widget.AppTheme.Button.IconButton"
+                    android:layout_width="38dp"
+                    android:layout_height="38dp"
+                    android:layout_marginEnd="4dp"
+                    android:contentDescription="@string/action_switch_grid_view"
+                    app:cornerRadius="24dp"
+                    app:icon="@drawable/ic_view_module"
+                    app:iconTint="@color/fontAppbar"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+            </androidx.constraintlayout.widget.ConstraintLayout>
+        </com.google.android.material.appbar.AppBarLayout>
+
         <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
             android:id="@+id/swipe_containing_list"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:footerDividersEnabled="false"
-            android:visibility="visible">
+            android:visibility="visible"
+            app:layout_behavior="@string/appbar_scrolling_view_behavior">
 
             <com.owncloud.android.ui.EmptyRecyclerView
                 android:id="@+id/list_root"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                />
+                android:layout_height="match_parent" />
         </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
 
-        <include layout="@layout/empty_list"/>
-
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
-        android:id="@+id/fab_main"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="end|bottom"
-        android:layout_alignParentEnd="true"
-        android:layout_marginBottom="@dimen/standard_margin"
-        android:layout_marginEnd="@dimen/standard_margin"
-        android:contentDescription="@string/fab_label"
-        android:visibility="gone" />
+        <include layout="@layout/empty_list" />
+
+        <com.google.android.material.floatingactionbutton.FloatingActionButton
+            android:id="@+id/fab_main"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true"
+            android:layout_gravity="end|bottom"
+            android:layout_marginEnd="@dimen/standard_margin"
+            android:layout_marginBottom="@dimen/standard_margin"
+            android:contentDescription="@string/fab_label"
+            android:visibility="gone"
+            app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" />
 
     </androidx.coordinatorlayout.widget.CoordinatorLayout>
 </RelativeLayout>

+ 10 - 0
src/main/res/values/styles.xml

@@ -316,4 +316,14 @@
         <item name="android:scaleType">fitCenter</item>
         <item name="android:layout_gravity">center_vertical</item>
     </style>
+
+    <style name="Widget.AppTheme.Button.IconButton" parent="Widget.MaterialComponents.Button.TextButton">
+        <item name="android:minWidth">0dp</item>
+        <item name="android:insetLeft">0dp</item>
+        <item name="android:insetTop">0dp</item>
+        <item name="android:insetRight">0dp</item>
+        <item name="android:insetBottom">0dp</item>
+        <item name="iconGravity">textStart</item>
+        <item name="iconPadding">0dp</item>
+    </style>
 </resources>