diff options
13 files changed, 198 insertions, 79 deletions
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/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); |