diff options
20 files changed, 285 insertions, 91 deletions
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/color/list_item_ripple_color.xml b/res/flag(com.android.documentsui.flags.use_material3)/color/list_item_ripple_color.xml index 6c2d0714e..85e5b46ce 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/color/list_item_ripple_color.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/color/list_item_ripple_color.xml @@ -17,6 +17,10 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:color="@android:color/transparent" /> + <!-- By default <ripple> introduces a gray-ish layer for the focused state which we don't + want, hence explicitly setting focused ripple color to transparent to get rid of that. + --> + <item android:state_focused="true" android:color="@android:color/transparent" /> <item android:state_selected="true" android:alpha="@dimen/ripple_overlay_alpha" android:color="?attr/colorOnPrimaryContainer" /> <item android:alpha="@dimen/ripple_overlay_alpha" diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/list_item_background.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/list_item_background.xml index 31bbec1f2..79c2eb1b7 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/drawable/list_item_background.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/list_item_background.xml @@ -26,6 +26,41 @@ <item> <selector> <!-- Selected --> + <item + android:state_selected="true" + android:state_focused="true" + android:state_hovered="true"> + <layer-list> + <item + android:bottom="@dimen/focus_ring_gap" + android:left="@dimen/focus_ring_gap" + android:right="@dimen/focus_ring_gap" + android:top="@dimen/focus_ring_gap"> + <shape> + <corners android:radius="@dimen/list_item_height" /> + <solid android:color="@color/list_item_selected_background_color" /> + </shape> + </item> + <item + android:bottom="@dimen/focus_ring_gap" + android:left="@dimen/focus_ring_gap" + android:right="@dimen/focus_ring_gap" + android:top="@dimen/focus_ring_gap"> + <shape android:tint="?attr/colorOnPrimaryContainer"> + <corners android:radius="@dimen/list_item_height" /> + <solid android:color="@color/overlay_hover_color_percentage" /> + </shape> + </item> + <item> + <shape> + <corners android:radius="@dimen/list_item_height" /> + <stroke + android:width="@dimen/focus_ring_width" + android:color="?attr/colorSecondary" /> + </shape> + </item> + </layer-list> + </item> <item android:state_selected="true" android:state_drag_hovered="true"> <layer-list> <item> @@ -104,6 +139,28 @@ </item> <!-- Unselected --> + <item android:state_focused="true" android:state_hovered="true"> + <layer-list> + <item + android:bottom="@dimen/focus_ring_gap" + android:left="@dimen/focus_ring_gap" + android:right="@dimen/focus_ring_gap" + android:top="@dimen/focus_ring_gap"> + <shape android:tint="?attr/colorOnSurface"> + <corners android:radius="@dimen/list_item_height" /> + <solid android:color="@color/overlay_hover_color_percentage" /> + </shape> + </item> + <item> + <shape> + <corners android:radius="@dimen/list_item_height" /> + <stroke + android:width="@dimen/focus_ring_width" + android:color="?attr/colorSecondary" /> + </shape> + </item> + </layer-list> + </item> <item android:state_drag_hovered="true"> <shape android:tint="?attr/colorOnSurface"> <corners android:radius="@dimen/list_item_height" /> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout-w600dp/fragment_save_cancel_button.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout-w600dp/fragment_save_cancel_button.xml new file mode 100644 index 000000000..e879b81ab --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout-w600dp/fragment_save_cancel_button.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2025 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<com.google.android.material.button.MaterialButton + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@android:id/button2" + style="@style/MaterialTonalButton" + app:cornerRadius="@dimen/button_corner_radius" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="4dp" + android:layout_marginEnd="4dp" + android:text="@android:string/cancel"/> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml index 8e23aad19..fc4a22bc6 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml @@ -89,7 +89,7 @@ android:id="@+id/container_save" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?android:attr/colorBackgroundFloating" /> + android:background="?attr/colorSurfaceContainer" /> </LinearLayout> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml index feaa34e6d..5496f0d84 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml @@ -32,7 +32,6 @@ android:paddingTop="@dimen/layout_padding_top" android:paddingBottom="@dimen/layout_padding_bottom" android:paddingEnd="@dimen/layout_padding_end"> - <!-- Navigation: left hand side. --> <FrameLayout android:id="@+id/container_roots" @@ -124,7 +123,7 @@ android:id="@+id/container_save" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?android:attr/colorBackgroundFloating" + android:background="?attr/colorSurfaceContainer" android:elevation="8dp" /> </LinearLayout> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick.xml index 742861a3e..a126492d0 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick.xml @@ -13,48 +13,59 @@ limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<androidx.constraintlayout.widget.ConstraintLayout + 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="wrap_content" - android:orientation="horizontal" - android:baselineAligned="false" - android:gravity="center_vertical|end" - android:paddingStart="@dimen/bottom_bar_padding" - android:paddingEnd="@dimen/bottom_bar_padding"> - - <com.google.android.material.button.MaterialButton - android:id="@android:id/button2" - style="?attr/materialButtonOutlinedStyle" - app:cornerRadius="@dimen/button_corner_radius" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="4dp" - android:layout_marginEnd="4dp" - android:text="@android:string/cancel" /> + android:paddingTop="@dimen/picker_saver_container_padding_top" + android:paddingBottom="@dimen/picker_saver_container_padding_bottom"> - <FrameLayout + <LinearLayout android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="wrap_content" + android:orientation="horizontal" + android:baselineAligned="false" + android:background="?attr/colorSurfaceContainer" + android:gravity="center_vertical|end" + android:paddingStart="@dimen/bottom_bar_padding" + android:paddingEnd="@dimen/bottom_bar_padding" + android:paddingTop="@dimen/picker_saver_padding_top" + android:paddingBottom="@dimen/picker_saver_padding_bottom"> + + <com.google.android.material.button.MaterialButton + android:id="@android:id/button2" + style="@style/MaterialTonalButton" + app:cornerRadius="@dimen/button_corner_radius" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/picker_saver_button_gap" + android:layout_marginEnd="@dimen/picker_saver_button_gap" + android:text="@android:string/cancel" /> <com.google.android.material.button.MaterialButton android:id="@android:id/button1" - style="?attr/materialButtonStyle" + style="@style/MaterialButton" app:cornerRadius="@dimen/button_corner_radius" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="4dp" android:backgroundTint="@color/fragment_pick_button_background_color" android:textColor="@color/fragment_pick_button_text_color" android:layout_marginEnd="4dp" /> - <!-- Handles touch events when button1 is disabled. --> - <FrameLayout - android:id="@+id/pick_button_overlay" - android:importantForAccessibility="no" - android:layout_width="match_parent" - android:layout_height="match_parent" /> + </LinearLayout> - </FrameLayout> + <!-- Handles touch events when button1 is disabled. --> + <View + android:id="@+id/pick_button_overlay" + android:layout_width="0dp" + android:layout_height="0dp" + android:background="@android:color/transparent" + android:visibility="gone" + android:importantForAccessibility="no" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> -</LinearLayout> +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save.xml index 401eaec88..416e4d6d2 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save.xml @@ -18,42 +18,40 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="@dimen/list_item_padding" - android:paddingEnd="@dimen/bottom_bar_padding" - android:orientation="horizontal" - android:baselineAligned="false" - android:gravity="center_vertical" - android:minHeight="?android:attr/listPreferredItemHeightSmall"> + android:paddingTop="@dimen/picker_saver_container_padding_top" + android:paddingBottom="@dimen/picker_saver_container_padding_bottom"> - <FrameLayout - android:layout_width="@dimen/icon_size" - android:layout_height="@dimen/icon_size" - android:layout_marginEnd="16dp"> - - <ImageView - android:id="@android:id/icon" - android:layout_width="@dimen/root_icon_size" - android:layout_height="match_parent" - android:scaleType="centerInside" - android:contentDescription="@null" /> - - </FrameLayout> - - <EditText - android:id="@android:id/title" - android:layout_width="0dp" + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_weight="1" - android:singleLine="true" - android:selectAllOnFocus="true" /> + android:paddingTop="@dimen/picker_saver_padding_top" + android:paddingBottom="@dimen/picker_saver_padding_bottom" + android:paddingEnd="@dimen/bottom_bar_padding" + android:orientation="horizontal" + android:baselineAligned="false" + android:gravity="center_vertical|end" + android:paddingStart="@dimen/list_item_padding"> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/title_wrapper" + style="?attr/textInputFilledStyle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:hint="@string/file_name_hint"> + <com.google.android.material.textfield.TextInputEditText + android:id="@android:id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:selectAllOnFocus="true" /> + </com.google.android.material.textfield.TextInputLayout> - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="match_parent"> + <include layout="@layout/fragment_save_cancel_button" /> <com.google.android.material.button.MaterialButton android:id="@android:id/button1" - style="@style/Widget.Material3.Button.UnelevatedButton" + style="@style/MaterialButton" app:cornerRadius="@dimen/button_corner_radius" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -61,7 +59,7 @@ android:layout_marginEnd="4dp" android:text="@string/menu_save"/> - <ProgressBar + <com.google.android.material.progressindicator.CircularProgressIndicator android:id="@android:id/progress" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -69,8 +67,8 @@ android:visibility="gone" android:indeterminate="true" android:padding="8dp" - style="?android:attr/progressBarStyle" /> + app:trackColor="?attr/colorSecondaryContainer" /> - </FrameLayout> + </LinearLayout> </LinearLayout> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save_cancel_button.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save_cancel_button.xml new file mode 100644 index 000000000..5179630c9 --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_save_cancel_button.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2025 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- The "Cancel" button is default invisible. On form factors with FEATURE_PC set, it is + updated to be shown always. --> +<com.google.android.material.button.MaterialButton + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@android:id/button2" + style="@style/Widget.Material3.Button.TonalButton" + app:cornerRadius="@dimen/button_corner_radius" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="4dp" + android:layout_marginEnd="4dp" + android:visibility="gone" + android:text="@android:string/cancel"/>
\ No newline at end of file diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml index a014d8866..bd85b7dac 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml @@ -35,8 +35,8 @@ android:orientation="horizontal" android:baselineAligned="false" android:paddingTop="@dimen/layout_padding_top" - android:paddingBottom="@dimen/layout_padding_bottom" android:paddingEnd="@dimen/layout_padding_end" + android:paddingBottom="@dimen/layout_padding_bottom" android:background="?attr/colorSurfaceContainer"> <!-- Navigation rail: left hand side. --> @@ -144,17 +144,17 @@ android:layout_marginTop="@dimen/main_container_section_gap" android:background="@drawable/main_container_bottom_section_background"> - <com.android.documentsui.HorizontalBreadcrumb - android:id="@+id/horizontal_breadcrumb" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> + <com.android.documentsui.HorizontalBreadcrumb + android:id="@+id/horizontal_breadcrumb" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> </LinearLayout> <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/container_save" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="?android:attr/colorBackgroundFloating" + android:background="?attr/colorSurfaceContainer" android:elevation="8dp" /> </LinearLayout> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml b/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml index 880d6c0b0..00c9a662a 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml @@ -31,5 +31,7 @@ <dimen name="table_header_padding_start">28dp</dimen> <!-- list_container_padding + list_item_padding_end --> <dimen name="table_header_padding_end">20dp</dimen> + + <dimen name="picker_saver_container_padding_bottom">0dp</dimen> </resources> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml index 0e532d39a..76e194c4f 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml @@ -158,6 +158,11 @@ <dimen name="main_container_section_gap">2dp</dimen> <dimen name="main_container_corner_radius_large">16dp</dimen> <dimen name="main_container_corner_radius_small">4dp</dimen> + <dimen name="picker_saver_padding_top">@dimen/space_extra_small_1</dimen> + <dimen name="picker_saver_padding_bottom">@dimen/space_extra_small_1</dimen> + <dimen name="picker_saver_button_gap">@dimen/space_extra_small_4</dimen> + <dimen name="picker_saver_container_padding_top">@dimen/space_small_1</dimen> + <dimen name="picker_saver_container_padding_bottom">@dimen/space_small_1</dimen> <dimen name="layout_padding_top">@dimen/space_small_1</dimen> <dimen name="layout_padding_bottom">@dimen/space_small_1</dimen> <dimen name="layout_padding_end">@dimen/space_small_1</dimen> diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml index 693679cf9..5d0687a37 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml @@ -90,6 +90,10 @@ <item name="android:textAppearance">@style/MaterialButtonTextAppearance</item> </style> + <style name="MaterialTonalButton" parent="@style/Widget.Material3.Button.TonalButton"> + <item name="android:textAppearance">@style/MaterialButtonTextAppearance</item> + </style> + <style name="MaterialOutlinedButton" parent="@style/Widget.Material3.Button.OutlinedButton"> <item name="android:textAppearance">@style/MaterialButtonTextAppearance</item> </style> diff --git a/res/values/strings.xml b/res/values/strings.xml index fc97d2c7d..f8ade4c47 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -611,4 +611,6 @@ <!-- Unicode Character “•” (U+2022). --> <string name="bullet">\u2022</string> + <!-- Text used at the top of the text field when saving a document. [CHAR_LIMIT=100] --> + <string name="file_name_hint">File name</string> </resources> diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java index ba50cfb32..89e9bc2d6 100644 --- a/src/com/android/documentsui/AbstractActionHandler.java +++ b/src/com/android/documentsui/AbstractActionHandler.java @@ -21,6 +21,7 @@ import static com.android.documentsui.base.DocumentInfo.getCursorString; import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.util.FlagUtils.isDesktopFileHandlingFlagEnabled; import static com.android.documentsui.util.FlagUtils.isUseSearchV2FlagEnabled; +import static com.android.documentsui.util.FlagUtils.isZipNgFlagEnabled; import android.app.PendingIntent; import android.content.ActivityNotFoundException; @@ -458,17 +459,17 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA private boolean viewDocument(DocumentInfo doc) { if (doc.isPartial()) { - Log.w(TAG, "Can't view partial file."); + Log.w(TAG, "Cannot view partial file"); return false; } - if (doc.isInArchive()) { - Log.w(TAG, "Can't view files in archives."); + if (!isZipNgFlagEnabled() && doc.isInArchive()) { + Log.w(TAG, "Cannot view file in archive"); return false; } if (doc.isDirectory()) { - Log.w(TAG, "Can't view directories."); + Log.w(TAG, "Cannot view directory"); return true; } diff --git a/src/com/android/documentsui/base/DocumentInfo.java b/src/com/android/documentsui/base/DocumentInfo.java index ad09c45cf..6306f14f1 100644 --- a/src/com/android/documentsui/base/DocumentInfo.java +++ b/src/com/android/documentsui/base/DocumentInfo.java @@ -17,6 +17,7 @@ package com.android.documentsui.base; import static com.android.documentsui.base.SharedMinimal.DEBUG; +import static com.android.documentsui.util.FlagUtils.isZipNgFlagEnabled; import android.content.ContentProviderClient; import android.content.ContentResolver; @@ -319,7 +320,8 @@ public class DocumentInfo implements Durable, Parcelable { // Containers are documents which can be opened in DocumentsUI as folders. public boolean isContainer() { - return isDirectory() || (isArchive() && !isInArchive() && !isPartial()); + return isDirectory() || (isArchive() && !isPartial() && (isZipNgFlagEnabled() + || !isInArchive())); } public boolean isVirtual() { @@ -342,7 +344,6 @@ public class DocumentInfo implements Durable, Parcelable { return userId.buildDocumentUriAsUser(authority, documentId); } - /** * Returns a tree document uri representing this {@link DocumentInfo}. The URI may contain user * information. Use this when uri is needed externally. diff --git a/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java b/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java index 8989853a0..8be400924 100644 --- a/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java +++ b/src/com/android/documentsui/dirlist/DirectoryAddonsAdapter.java @@ -16,6 +16,8 @@ package com.android.documentsui.dirlist; +import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; + import android.os.UserManager; import android.view.ViewGroup; @@ -207,6 +209,11 @@ final class DirectoryAddonsAdapter extends DocumentsAdapter { return; } + if (isUseMaterial3FlagEnabled()) { + // Do not add a visual break between folders and documents in Material3. + return; + } + // Walk down the list of IDs till we encounter something that's not a directory, and // insert a whitespace element - this introduces a visual break in the grid between // folders and documents. diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java index 6de42db59..2ea906a60 100644 --- a/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -23,6 +23,7 @@ import static com.android.documentsui.base.State.MODE_GRID; import static com.android.documentsui.base.State.MODE_LIST; import static com.android.documentsui.util.FlagUtils.isDesktopFileHandlingFlagEnabled; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; +import static com.android.documentsui.util.FlagUtils.isZipNgFlagEnabled; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -946,11 +947,13 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mSelectionMgr.copySelection(selection); final int id = item.getItemId(); - if (isDesktopFileHandlingFlagEnabled() && id == R.id.dir_menu_open) { - // On desktop, "open" is displayed in file management mode (i.e. `files.MenuManager`). - // This menu item behaves the same as double click on the menu item which is handled by - // onItemActivated but since onItemActivated requires a RecylcerView ItemDetails, we're - // using viewDocument that takes a Selection. + if ((isDesktopFileHandlingFlagEnabled() && id == R.id.dir_menu_open) + || (isZipNgFlagEnabled() && id == R.id.dir_menu_browse)) { + // The "Open" menu item is displayed in desktop mode. + // The "Browse" menu item is displayed for supported archives in advanced ZIP mode. + // These menu items behave the same as a double click on the matching document which + // is handled by onItemActivated but since onItemActivated requires a RecyclerView + // ItemDetails, we're using viewDocument that takes a Selection. viewDocument(selection); return true; } else if (id == R.id.action_menu_select || id == R.id.dir_menu_open) { diff --git a/src/com/android/documentsui/dirlist/SelectionMetadata.java b/src/com/android/documentsui/dirlist/SelectionMetadata.java index 0559a3b80..0d0644502 100644 --- a/src/com/android/documentsui/dirlist/SelectionMetadata.java +++ b/src/com/android/documentsui/dirlist/SelectionMetadata.java @@ -18,6 +18,7 @@ package com.android.documentsui.dirlist; import static com.android.documentsui.base.DocumentInfo.getCursorInt; import static com.android.documentsui.base.DocumentInfo.getCursorString; +import static com.android.documentsui.util.FlagUtils.isZipNgFlagEnabled; import android.database.Cursor; import android.provider.DocumentsContract.Document; @@ -184,6 +185,7 @@ public class SelectionMetadata extends SelectionObserver<String> @Override public boolean canOpen() { - return size() == 1 && mDirectoryCount == 0 && mInArchiveCount == 0 && mPartialCount == 0; + return mFileCount == 1 && mDirectoryCount == 0 && mPartialCount == 0 && ( + isZipNgFlagEnabled() || mInArchiveCount == 0); } } diff --git a/src/com/android/documentsui/picker/PickFragment.java b/src/com/android/documentsui/picker/PickFragment.java index e9610a510..66f05fa0f 100644 --- a/src/com/android/documentsui/picker/PickFragment.java +++ b/src/com/android/documentsui/picker/PickFragment.java @@ -22,7 +22,9 @@ import static com.android.documentsui.services.FileOperationService.OPERATION_DE import static com.android.documentsui.services.FileOperationService.OPERATION_EXTRACT; import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE; import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN; +import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; +import android.content.pm.PackageManager; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -179,13 +181,19 @@ public class PickFragment extends Fragment { switch (mAction) { case State.ACTION_OPEN_TREE: mPick.setText(getString(R.string.open_tree_button)); - mPick.setWidth(Integer.MAX_VALUE); - mCancel.setVisibility(View.GONE); + // On laptops we want the "Use this folder" button to appear with the "Cancel" + // button as a back gesture with a mouse is not easy. + if (!isUseMaterial3FlagEnabled() + || !getActivity().getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_PC)) { + mPick.setWidth(Integer.MAX_VALUE); + mCancel.setVisibility(View.GONE); + mPickOverlay.setVisibility( + mPickTarget.isBlockedFromTree() && mRestrictScopeStorage + ? View.VISIBLE + : View.GONE); + } mPick.setEnabled(!(mPickTarget.isBlockedFromTree() && mRestrictScopeStorage)); - mPickOverlay.setVisibility( - mPickTarget.isBlockedFromTree() && mRestrictScopeStorage - ? View.VISIBLE - : View.GONE); break; case State.ACTION_PICK_COPY_DESTINATION: int titleId; diff --git a/src/com/android/documentsui/picker/SaveFragment.java b/src/com/android/documentsui/picker/SaveFragment.java index f881768b9..8316688e7 100644 --- a/src/com/android/documentsui/picker/SaveFragment.java +++ b/src/com/android/documentsui/picker/SaveFragment.java @@ -16,7 +16,11 @@ package com.android.documentsui.picker; +import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; + import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Editable; import android.text.TextUtils; @@ -42,6 +46,9 @@ import com.android.documentsui.base.BooleanConsumer; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.Shared; +import com.google.android.material.button.MaterialButton; +import com.google.android.material.textfield.TextInputLayout; + /** * Display document title editor and save button. */ @@ -54,6 +61,7 @@ public class SaveFragment extends Fragment { private DocumentInfo mReplaceTarget; private EditText mDisplayName; private TextView mSave; + private MaterialButton mCancel; private ProgressBar mProgress; private boolean mIgnoreNextEdit; @@ -84,9 +92,16 @@ public class SaveFragment extends Fragment { final View view = inflater.inflate(R.layout.fragment_save, container, false); - final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); - icon.setImageDrawable( - IconUtils.loadMimeIcon(context, getArguments().getString(EXTRA_MIME_TYPE))); + final Drawable icon = + IconUtils.loadMimeIcon(context, getArguments().getString(EXTRA_MIME_TYPE)); + if (isUseMaterial3FlagEnabled()) { + final TextInputLayout titleWrapper = + (TextInputLayout) view.findViewById(R.id.title_wrapper); + titleWrapper.setStartIconDrawable(icon); + } else { + final ImageView iconHolder = view.findViewById(android.R.id.icon); + iconHolder.setImageDrawable(icon); + } mDisplayName = (EditText) view.findViewById(android.R.id.title); mDisplayName.addTextChangedListener(mDisplayNameWatcher); @@ -122,6 +137,19 @@ public class SaveFragment extends Fragment { mSave.setOnClickListener(mSaveListener); mSave.setEnabled(false); + mCancel = (MaterialButton) view.findViewById(android.R.id.button2); + // For >600dp, this button is always available (via the values-600dp layout override). + // However on smaller layouts, the button is default GONE to save on space (the back gesture + // can cancel the saver) and when FEATURE_PC is set a cancel button is required due to the + // lack of a back gesture (mainly mouse support). + if (isUseMaterial3FlagEnabled() + && mCancel != null + && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) { + mCancel.setOnClickListener(mCancelListener); + mCancel.setVisibility(View.VISIBLE); + mCancel.setEnabled(true); + } + mProgress = (ProgressBar) view.findViewById(android.R.id.progress); return view; @@ -173,6 +201,13 @@ public class SaveFragment extends Fragment { }; + private View.OnClickListener mCancelListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + mInjector.actions.finishPicking(); + } + }; + private void performSave() { if (mReplaceTarget != null) { mInjector.actions.saveDocument(getChildFragmentManager(), mReplaceTarget); |