Loading res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick_files_m3.xml 0 → 100644 +52 −0 Original line number Diff line number Diff line <?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. --> <LinearLayout 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:paddingStart="@dimen/picker_saver_padding_start" android:paddingEnd="@dimen/picker_saver_padding_end" android:paddingBottom="@dimen/picker_saver_padding_bottom" android:paddingTop="@dimen/picker_saver_padding_top" android:background="?attr/colorSurfaceContainer" android:baselineAligned="false" android:gravity="center_vertical|end" android:orientation="horizontal"> <com.google.android.material.button.MaterialButton android:id="@+id/button_cancel" style="@style/MaterialTonalButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/picker_saver_button_gap" android:layout_marginTop="@dimen/picker_saver_button_gap" android:layout_marginBottom="@dimen/picker_saver_button_gap" android:text="@android:string/cancel" app:cornerRadius="@dimen/button_corner_radius_m3" /> <com.google.android.material.button.MaterialButton android:id="@+id/button_pick" style="@style/MaterialButtonM3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/picker_saver_button_gap" android:layout_marginTop="@dimen/picker_saver_button_gap" android:layout_marginBottom="@dimen/picker_saver_button_gap" android:text="@string/menu_select" app:cornerRadius="@dimen/button_corner_radius_m3" /> </LinearLayout> src/com/android/documentsui/DocsSelectionHelper.java +37 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.recyclerview.selection.Selection; import androidx.recyclerview.selection.SelectionTracker; import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import java.util.HashSet; import java.util.Set; /** Loading @@ -42,6 +43,8 @@ public final class DocsSelectionHelper extends SelectionTracker<String> { // See: b/69306667. private SelectionTracker<String> mDelegate = new StubSelectionTracker<>(); private Set<ResetObserver> mResetObservers = new HashSet<>(); @VisibleForTesting DocsSelectionHelper(DelegateFactory factory) { mFactory = factory; Loading @@ -52,6 +55,40 @@ public final class DocsSelectionHelper extends SelectionTracker<String> { mDelegate.clearSelection(); } mDelegate = mFactory.create(selectionTracker); for (ResetObserver observer : mResetObservers) { observer.onReset(); } } /** * Observes when the DocsSelectionHelper gets reset (this happens on every initialization and * re-initialization). */ public abstract static class ResetObserver { /** * Called when the DocsSelectionHelper resets. */ public void onReset() { } } /** * Adds a ResetObserver. * @param observer */ public void addResetObserver(ResetObserver observer) { if (mResetObservers.contains(observer)) { return; } mResetObservers.add(observer); } /** * Removes a ResetObserver. * @param observer */ public void removeResetObserver(ResetObserver observer) { mResetObservers.remove(observer); } @Override Loading src/com/android/documentsui/picker/ActionHandler.java +27 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.android.documentsui.base.State.ACTION_GET_CONTENT; import static com.android.documentsui.base.State.ACTION_OPEN; import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import static java.util.regex.Pattern.CASE_INSENSITIVE; Loading Loading @@ -71,6 +72,7 @@ import com.android.documentsui.util.FileUtils; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; import java.util.regex.Pattern; Loading Loading @@ -427,6 +429,9 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH return !doc.isContainer(); } /** * Picks a folder for the ACTION_OPEN_TREE or ACTION_PICK_COPY_DESTINATION picker. */ void pickDocument(FragmentManager fm, DocumentInfo pickTarget) { assert (pickTarget != null); mInjector.pickResult.increaseActionCount(); Loading @@ -445,6 +450,28 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH } } /** * Picks selected documents for the ACTION_OPEN or ACTION_GET_CONTENT picker. */ void pickSelected() { if (!isUseMaterial3FlagEnabled()) { return; } assert (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT); List<DocumentInfo> selection = mInjector.getModel().getDocuments( mInjector.selectionMgr.getSelection()); if (selection.isEmpty()) { Log.w(TAG, "There are no selected files"); return; } if (selection.size() > 1) { mActivity.onDocumentsPicked(selection); } else { mActivity.onDocumentPicked(selection.getFirst()); } } void saveDocument( String mimeType, String displayName, BooleanConsumer inProgressStateListener) { assert (mState.action == ACTION_CREATE); Loading src/com/android/documentsui/picker/MenuManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.documentsui.base.State.ACTION_GET_CONTENT; import static com.android.documentsui.base.State.ACTION_OPEN; import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import static com.android.documentsui.util.Material3Config.getRes; import android.database.Cursor; Loading Loading @@ -137,7 +138,8 @@ public final class MenuManager extends com.android.documentsui.MenuManager { @Override protected void updateSelect(MenuItem select, SelectionDetails selectionDetails) { Menus.setEnabledAndVisible(select, (mState.action == ACTION_GET_CONTENT Menus.setEnabledAndVisible(select, !isUseMaterial3FlagEnabled() && (mState.action == ACTION_GET_CONTENT || mState.action == ACTION_OPEN) && selectionDetails.size() > 0); select.setTitle(getRes(R.string.menu_select)); Loading src/com/android/documentsui/picker/PickActivity.java +4 −1 Original line number Diff line number Diff line Loading @@ -245,8 +245,11 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { } else if (mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { PickDirectoryFragment.show(getSupportFragmentManager()); } else if (isUseMaterial3FlagEnabled() && (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT)) { PickFilesFragment.show(getSupportFragmentManager(), mState.action); } else if (!isUseMaterial3FlagEnabled()) { // If PickFragment or SaveFragment does not show, // If PickDirectoryFragment, PickFilesFragment or SaveFragment does not show, // Set save container background to transparent for edge to edge nav bar. // However when the use_material3 flag is on, the file path bar is at the bottom of the // layout and hence the edge to edge nav bar is no longer required. Loading Loading
res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_pick_files_m3.xml 0 → 100644 +52 −0 Original line number Diff line number Diff line <?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. --> <LinearLayout 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:paddingStart="@dimen/picker_saver_padding_start" android:paddingEnd="@dimen/picker_saver_padding_end" android:paddingBottom="@dimen/picker_saver_padding_bottom" android:paddingTop="@dimen/picker_saver_padding_top" android:background="?attr/colorSurfaceContainer" android:baselineAligned="false" android:gravity="center_vertical|end" android:orientation="horizontal"> <com.google.android.material.button.MaterialButton android:id="@+id/button_cancel" style="@style/MaterialTonalButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="@dimen/picker_saver_button_gap" android:layout_marginTop="@dimen/picker_saver_button_gap" android:layout_marginBottom="@dimen/picker_saver_button_gap" android:text="@android:string/cancel" app:cornerRadius="@dimen/button_corner_radius_m3" /> <com.google.android.material.button.MaterialButton android:id="@+id/button_pick" style="@style/MaterialButtonM3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/picker_saver_button_gap" android:layout_marginTop="@dimen/picker_saver_button_gap" android:layout_marginBottom="@dimen/picker_saver_button_gap" android:text="@string/menu_select" app:cornerRadius="@dimen/button_corner_radius_m3" /> </LinearLayout>
src/com/android/documentsui/DocsSelectionHelper.java +37 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import androidx.recyclerview.selection.Selection; import androidx.recyclerview.selection.SelectionTracker; import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver; import java.util.HashSet; import java.util.Set; /** Loading @@ -42,6 +43,8 @@ public final class DocsSelectionHelper extends SelectionTracker<String> { // See: b/69306667. private SelectionTracker<String> mDelegate = new StubSelectionTracker<>(); private Set<ResetObserver> mResetObservers = new HashSet<>(); @VisibleForTesting DocsSelectionHelper(DelegateFactory factory) { mFactory = factory; Loading @@ -52,6 +55,40 @@ public final class DocsSelectionHelper extends SelectionTracker<String> { mDelegate.clearSelection(); } mDelegate = mFactory.create(selectionTracker); for (ResetObserver observer : mResetObservers) { observer.onReset(); } } /** * Observes when the DocsSelectionHelper gets reset (this happens on every initialization and * re-initialization). */ public abstract static class ResetObserver { /** * Called when the DocsSelectionHelper resets. */ public void onReset() { } } /** * Adds a ResetObserver. * @param observer */ public void addResetObserver(ResetObserver observer) { if (mResetObservers.contains(observer)) { return; } mResetObservers.add(observer); } /** * Removes a ResetObserver. * @param observer */ public void removeResetObserver(ResetObserver observer) { mResetObservers.remove(observer); } @Override Loading
src/com/android/documentsui/picker/ActionHandler.java +27 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static com.android.documentsui.base.State.ACTION_GET_CONTENT; import static com.android.documentsui.base.State.ACTION_OPEN; import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import static java.util.regex.Pattern.CASE_INSENSITIVE; Loading Loading @@ -71,6 +72,7 @@ import com.android.documentsui.util.FileUtils; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; import java.util.regex.Pattern; Loading Loading @@ -427,6 +429,9 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH return !doc.isContainer(); } /** * Picks a folder for the ACTION_OPEN_TREE or ACTION_PICK_COPY_DESTINATION picker. */ void pickDocument(FragmentManager fm, DocumentInfo pickTarget) { assert (pickTarget != null); mInjector.pickResult.increaseActionCount(); Loading @@ -445,6 +450,28 @@ class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionH } } /** * Picks selected documents for the ACTION_OPEN or ACTION_GET_CONTENT picker. */ void pickSelected() { if (!isUseMaterial3FlagEnabled()) { return; } assert (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT); List<DocumentInfo> selection = mInjector.getModel().getDocuments( mInjector.selectionMgr.getSelection()); if (selection.isEmpty()) { Log.w(TAG, "There are no selected files"); return; } if (selection.size() > 1) { mActivity.onDocumentsPicked(selection); } else { mActivity.onDocumentPicked(selection.getFirst()); } } void saveDocument( String mimeType, String displayName, BooleanConsumer inProgressStateListener) { assert (mState.action == ACTION_CREATE); Loading
src/com/android/documentsui/picker/MenuManager.java +3 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static com.android.documentsui.base.State.ACTION_GET_CONTENT; import static com.android.documentsui.base.State.ACTION_OPEN; import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import static com.android.documentsui.util.Material3Config.getRes; import android.database.Cursor; Loading Loading @@ -137,7 +138,8 @@ public final class MenuManager extends com.android.documentsui.MenuManager { @Override protected void updateSelect(MenuItem select, SelectionDetails selectionDetails) { Menus.setEnabledAndVisible(select, (mState.action == ACTION_GET_CONTENT Menus.setEnabledAndVisible(select, !isUseMaterial3FlagEnabled() && (mState.action == ACTION_GET_CONTENT || mState.action == ACTION_OPEN) && selectionDetails.size() > 0); select.setTitle(getRes(R.string.menu_select)); Loading
src/com/android/documentsui/picker/PickActivity.java +4 −1 Original line number Diff line number Diff line Loading @@ -245,8 +245,11 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { } else if (mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { PickDirectoryFragment.show(getSupportFragmentManager()); } else if (isUseMaterial3FlagEnabled() && (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT)) { PickFilesFragment.show(getSupportFragmentManager(), mState.action); } else if (!isUseMaterial3FlagEnabled()) { // If PickFragment or SaveFragment does not show, // If PickDirectoryFragment, PickFilesFragment or SaveFragment does not show, // Set save container background to transparent for edge to edge nav bar. // However when the use_material3 flag is on, the file path bar is at the bottom of the // layout and hence the edge to edge nav bar is no longer required. Loading