summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Wenbo Jie <wenbojie@google.com> 2024-12-23 05:25:57 +0000
committer Wenbo Jie <wenbojie@google.com> 2025-01-20 15:13:45 +0000
commit89c4d019dab08a2bc098ea95d9a9daa7952c176c (patch)
tree9e2901e6c216a6589244a9a2fcf5f778a19a3e8c
parent28fdd411e9c164297dc62dd198b3a79367652997 (diff)
[DocsUI M3] Add navigation rail layout for medium size screen
* Add a new layout nav_rail_layout for medium size >=600 && <900 which also uses DrawerLayout but adds a narrower sidebar with icon/label only. * Reuse RootsFragment to render Navigation rail so we can keep all existing functionality for navigation drawer on navigation rail. We store the layout ID on the RootsFragment argument to distinguish which layout is rendering, in medium size layout, 2 instances of RootsFragment will be rendered: one for the navigation drawer, the other for navigation rail. * A new layout nav_rail_item_root is created to cater the layout for navigation rail items. * Extend the existing navigation drawer item classes to create the corresponding navigation rail item classes so we can use different layout for navigation rail items. Check the bug item for demo. Bug: 381958615 Test: Manual inpsection Flag: com.android.documentsui.flags.use_material3 Change-Id: I8fac4646031e248020755327caed6b427b5d08cf
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/color/nav_rail_item_text_color.xml21
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_background.xml23
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_background.xml145
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_mask.xml21
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_nav_rail_roots.xml25
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_item_root.xml55
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml129
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml2
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/layouts.xml20
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values-w900dp/dimens.xml1
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml5
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml20
-rw-r--r--res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml5
-rw-r--r--src/com/android/documentsui/BaseActivity.java15
-rw-r--r--src/com/android/documentsui/DrawerController.java5
-rw-r--r--src/com/android/documentsui/files/FilesActivity.java9
-rw-r--r--src/com/android/documentsui/picker/PickActivity.java10
-rw-r--r--src/com/android/documentsui/sidebar/AppItem.java13
-rw-r--r--src/com/android/documentsui/sidebar/NavRailAppItem.java48
-rw-r--r--src/com/android/documentsui/sidebar/NavRailProfileItem.java47
-rw-r--r--src/com/android/documentsui/sidebar/NavRailRootAndAppItem.java40
-rw-r--r--src/com/android/documentsui/sidebar/NavRailRootItem.java52
-rw-r--r--src/com/android/documentsui/sidebar/ProfileItem.java7
-rw-r--r--src/com/android/documentsui/sidebar/RootAndAppItem.java17
-rw-r--r--src/com/android/documentsui/sidebar/RootItem.java12
-rw-r--r--src/com/android/documentsui/sidebar/RootsFragment.java128
26 files changed, 851 insertions, 24 deletions
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/color/nav_rail_item_text_color.xml b/res/flag(com.android.documentsui.flags.use_material3)/color/nav_rail_item_text_color.xml
new file mode 100644
index 000000000..ec5aecb33
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/color/nav_rail_item_text_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_activated="true" android:color="?attr/colorSecondary" />
+ <item android:color="?attr/colorOnSurfaceVariant" />
+</selector>
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_background.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_background.xml
new file mode 100644
index 000000000..7809766cd
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- By default the nav rail item has a grey background when it's focused, but we need the
+ background to be put on the icon inside, so we override the focus background color to be
+ transparent here.
+ -->
+ <item android:state_focused="true" android:drawable="@android:color/transparent" />
+</selector> \ No newline at end of file
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_background.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_background.xml
new file mode 100644
index 000000000..7864321af
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_background.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:color="@color/item_root_ripple_color">
+
+ <!-- The mask below only works for the ripple itself, doesn't work for other <item>s, we
+ need to explicitly apply the drawable if the other items also need this mask. -->
+ <item
+ android:id="@android:id/mask"
+ android:drawable="@drawable/nav_rail_item_icon_mask"/>
+
+ <item>
+ <selector>
+ <!-- Selected (activated). -->
+ <!-- Highlight: when dragging files over the item. -->
+ <item
+ android:state_activated="true"
+ app:state_highlighted="true">
+ <layer-list>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="?attr/colorSecondaryContainer" />
+ </shape>
+ </item>
+ <item>
+ <shape android:tint="?attr/colorOnSecondaryContainer">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+ </layer-list>
+ </item>
+ <item
+ android:state_activated="true"
+ android:state_pressed="true">
+ <layer-list>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="?attr/colorSecondaryContainer" />
+ </shape>
+ </item>
+ <item>
+ <shape android:tint="?attr/colorOnSecondaryContainer">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+ </layer-list>
+ </item>
+ <item
+ android:state_activated="true"
+ android:state_focused="true">
+ <layer-list>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="?attr/colorSecondaryContainer" />
+ </shape>
+ </item>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <stroke
+ android:width="@dimen/focus_ring_width"
+ android:color="?attr/colorSecondary" />
+ </shape>
+ </item>
+ </layer-list>
+ </item>
+ <item
+ android:state_activated="true"
+ android:state_hovered="true">
+ <layer-list>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="?attr/colorSecondaryContainer" />
+ </shape>
+ </item>
+ <item>
+ <shape android:tint="?attr/colorOnSecondaryContainer">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+ </layer-list>
+ </item>
+ <item android:state_activated="true">
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="?attr/colorSecondaryContainer" />
+ </shape>
+ </item>
+
+ <!-- Unselected. -->
+ <item app:state_highlighted="true">
+ <shape android:tint="?attr/colorOnSurface">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape android:tint="?attr/colorOnSurface">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape>
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <stroke
+ android:width="@dimen/focus_ring_width"
+ android:color="?attr/colorSecondary" />
+ </shape>
+ </item>
+ <item android:state_hovered="true">
+ <shape android:tint="?attr/colorOnSurface">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius" />
+ <solid android:color="@color/overlay_color_percentage_10" />
+ </shape>
+ </item>
+
+ <!-- Default: use the container background. -->
+ <item android:drawable="@android:color/transparent" />
+ </selector>
+ </item>
+</ripple> \ No newline at end of file
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_mask.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_mask.xml
new file mode 100644
index 000000000..fd2a14b8d
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/nav_rail_item_icon_mask.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <corners android:radius="@dimen/nav_rail_item_icon_bg_radius"/>
+ <!-- The color here doesn't matter, it's just being used as a mask. -->
+ <solid android:color="@android:color/white" />
+</shape> \ No newline at end of file
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_nav_rail_roots.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_nav_rail_roots.xml
new file mode 100644
index 000000000..7848dea0b
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fragment_nav_rail_roots.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.android.documentsui.sidebar.RootsList xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/roots_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:keyboardNavigationCluster="true"
+ android:divider="@null"
+ android:focusable="false"
+ android:descendantFocusability="afterDescendants"
+ style="@style/NavRailStyle"/>
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_item_root.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_item_root.xml
new file mode 100644
index 000000000..461027c73
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_item_root.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.android.documentsui.sidebar.RootItemView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/nav_rail_item_height"
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:baselineAligned="false"
+ android:clickable="true"
+ android:focusable="true"
+ style="@style/NavRailItemStyle">
+
+ <LinearLayout
+ android:layout_width="@dimen/nav_rail_item_icon_bg_width"
+ android:layout_height="@dimen/nav_rail_item_icon_bg_height"
+ android:gravity="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/nav_rail_item_icon_background">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/root_icon_size"
+ android:layout_height="@dimen/root_icon_size"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textAlignment="center"
+ android:duplicateParentState="true"
+ style="@style/NavRailItemTextStyle" />
+
+</com.android.documentsui.sidebar.RootItemView>
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
new file mode 100644
index 000000000..5d753f336
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<!-- CoordinatorLayout is necessary for various components (e.g. Snackbars, and
+ floating action buttons) to operate correctly. -->
+<androidx.coordinatorlayout.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/coordinator_layout">
+
+ <androidx.drawerlayout.widget.DrawerLayout
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Main section -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ 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:background="?attr/colorSurfaceContainer">
+
+ <!-- Navigation rail: left hand side. -->
+ <FrameLayout
+ android:id="@+id/nav_rail_container_roots"
+ android:layout_width="144dp"
+ android:layout_height="match_parent"
+ />
+
+ <!-- Main container for the right hand side. -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@drawable/main_container_background"
+ android:paddingTop="@dimen/main_container_padding_top">
+
+ <com.google.android.material.appbar.MaterialToolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:layout_marginTop="@dimen/action_bar_margin"
+ android:touchscreenBlocksFocus="false">
+
+ <TextView
+ android:id="@+id/searchbar_title"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:gravity="center_vertical"
+ android:text="@string/search_bar_hint"
+ android:textAppearance="@style/SearchBarTitle" />
+
+ </com.google.android.material.appbar.MaterialToolbar>
+
+ <include layout="@layout/directory_header" />
+
+ <!-- Main list area (file list/grid or search results). -->
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+ <FrameLayout
+ android:id="@+id/container_directory"
+ android:clipToPadding="false"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <FrameLayout
+ android:id="@+id/container_search_fragment"
+ android:clipToPadding="false"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </FrameLayout>
+
+ <!-- Footer of right hand side: Breadcrumbs and Picker footer. -->
+ <com.android.documentsui.HorizontalBreadcrumb
+ android:id="@+id/horizontal_breadcrumb"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <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:elevation="8dp" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <!-- Drawer section -->
+ <LinearLayout
+ android:id="@+id/drawer_roots"
+ android:layout_width="256dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:orientation="vertical">
+
+ <FrameLayout
+ android:id="@+id/container_roots"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ </androidx.drawerlayout.widget.DrawerLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
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 4707991f6..2781026e9 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
@@ -23,7 +23,7 @@
we zero here, to avoid pushing the title further. -->
<dimen name="search_bar_text_margin_start">0dp</dimen>
- <dimen name="toolbar_padding_start">@dimen/main_container_padding_start</dimen>
+ <dimen name="toolbar_padding_start">@dimen/space_small_3</dimen>
<dimen name="list_container_padding">@dimen/space_extra_small_6</dimen>
</resources>
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/layouts.xml b/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/layouts.xml
new file mode 100644
index 000000000..4b0634d54
--- /dev/null
+++ b/res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/layouts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<resources>
+ <item name="documents_activity" type="layout">@layout/nav_rail_layout</item>
+ <item name="files_activity" type="layout">@layout/nav_rail_layout</item>
+</resources>
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values-w900dp/dimens.xml b/res/flag(com.android.documentsui.flags.use_material3)/values-w900dp/dimens.xml
index 51b1f7bdc..d37f3af68 100644
--- a/res/flag(com.android.documentsui.flags.use_material3)/values-w900dp/dimens.xml
+++ b/res/flag(com.android.documentsui.flags.use_material3)/values-w900dp/dimens.xml
@@ -32,6 +32,7 @@
<dimen name="main_container_padding_top">@dimen/space_extra_small_6</dimen>
+ <dimen name="toolbar_padding_start">@dimen/main_container_padding_start</dimen>
<dimen name="toolbar_padding_end">@dimen/space_small_3</dimen>
<dimen name="drawer_padding_top">@dimen/space_small_1</dimen>
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 47d0049a4..2c2d54f34 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
@@ -81,6 +81,11 @@
<dimen name="drawer_item_text_margin_start">12dp</dimen>
<dimen name="drawer_item_action_icon_margin_start">4dp</dimen>
+ <dimen name="nav_rail_item_height">64dp</dimen>
+ <dimen name="nav_rail_item_icon_bg_radius">16dp</dimen>
+ <dimen name="nav_rail_item_icon_bg_width">56dp</dimen>
+ <dimen name="nav_rail_item_icon_bg_height">32dp</dimen>
+
<dimen name="drag_shadow_width">176dp</dimen>
<dimen name="drag_shadow_height">64dp</dimen>
<dimen name="drag_shadow_radius">4dp</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 4c61e5152..5fde94ab8 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
@@ -166,4 +166,24 @@
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">@style/FileItemLabelText</item>
</style>
+
+ <style name="NavRailStyle" parent="">
+ <item name="android:background">?attr/colorSurfaceContainer</item>
+ <item name="android:paddingHorizontal">@dimen/space_small_3</item>
+ <item name="android:paddingTop">@dimen/space_extra_small_6</item>
+ <item name="android:paddingBottom">@dimen/space_small_1</item>
+ <item name="android:scrollbarStyle">outsideOverlay</item>
+ <item name="android:clipToPadding">false</item>
+ </style>
+
+ <style name="NavRailItemStyle" parent="">
+ <item name="android:background">@drawable/nav_rail_item_background</item>
+ <item name="android:paddingVertical">6dp</item>
+ </style>
+
+ <style name="NavRailItemTextStyle" parent="">
+ <item name="android:layout_marginTop">4dp</item>
+ <item name="android:textColor">@color/nav_rail_item_text_color</item>
+ <item name="android:textAppearance">@style/NavRailItemTextAppearance</item>
+ </style>
</resources>
diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml
index fb6d0e472..717295315 100644
--- a/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml
+++ b/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml
@@ -141,4 +141,9 @@
<style name="Subhead" parent="@style/TextAppearance.Material3.BodyLarge">
<item name="fontFamily">@string/config_fontFamily</item>
</style>
+
+ <style name="NavRailItemTextAppearance" parent="@style/TextAppearance.Material3.LabelMedium">
+ <item name="fontFamily">@string/config_fontFamily</item>
+ </style>
+
</resources>
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index fe81fbf16..4c25b3608 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -358,6 +358,14 @@ public abstract class BaseActivity
if (roots != null) {
roots.onSelectedUserChanged();
}
+ if (useMaterial3()) {
+ final RootsFragment navRailRoots =
+ RootsFragment.getNavRail(getSupportFragmentManager());
+ if (navRailRoots != null) {
+ navRailRoots.onSelectedUserChanged();
+ }
+ }
+
if (mState.stack.size() <= 1) {
// We do not load cross-profile root if the stack contains two documents. The
@@ -690,6 +698,13 @@ public abstract class BaseActivity
if (roots != null) {
roots.onCurrentRootChanged();
}
+ if (useMaterial3()) {
+ final RootsFragment navRailRoots =
+ RootsFragment.getNavRail(getSupportFragmentManager());
+ if (navRailRoots != null) {
+ navRailRoots.onCurrentRootChanged();
+ }
+ }
String appName = getString(R.string.files_label);
String currentTitle = getTitle() != null ? getTitle().toString() : "";
diff --git a/src/com/android/documentsui/DrawerController.java b/src/com/android/documentsui/DrawerController.java
index a988635fd..88c41b3f2 100644
--- a/src/com/android/documentsui/DrawerController.java
+++ b/src/com/android/documentsui/DrawerController.java
@@ -127,7 +127,10 @@ public abstract class DrawerController implements DrawerListener {
if (activityConfig.dragAndDropEnabled()) {
View edge = layout.findViewById(R.id.drawer_edge);
- edge.setOnDragListener(new ItemDragListener<>(this, SPRING_TIMEOUT));
+ // nav_rail_layout also uses DrawerLayout, but it doesn't have drawer edge.
+ if (edge != null) {
+ edge.setOnDragListener(new ItemDragListener<>(this, SPRING_TIMEOUT));
+ }
}
}
diff --git a/src/com/android/documentsui/files/FilesActivity.java b/src/com/android/documentsui/files/FilesActivity.java
index 1ebe2374f..1da0d8f2b 100644
--- a/src/com/android/documentsui/files/FilesActivity.java
+++ b/src/com/android/documentsui/files/FilesActivity.java
@@ -17,6 +17,7 @@
package com.android.documentsui.files;
import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
+import static com.android.documentsui.flags.Flags.useMaterial3;
import android.app.ActivityManager.TaskDescription;
import android.content.Intent;
@@ -181,6 +182,14 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
RootsFragment.show(getSupportFragmentManager(), /* includeApps= */ false,
/* intent= */ null);
+ if (useMaterial3()) {
+ View navRailRoots = findViewById(R.id.nav_rail_container_roots);
+ if (navRailRoots != null) {
+ // Medium layout, populate navigation rail layout.
+ RootsFragment.showNavRail(getSupportFragmentManager(), /* includeApps= */ false,
+ /* intent= */ null);
+ }
+ }
final Intent intent = getIntent();
diff --git a/src/com/android/documentsui/picker/PickActivity.java b/src/com/android/documentsui/picker/PickActivity.java
index e9b91b1a0..481b67e77 100644
--- a/src/com/android/documentsui/picker/PickActivity.java
+++ b/src/com/android/documentsui/picker/PickActivity.java
@@ -21,6 +21,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.flags.Flags.useMaterial3;
import android.content.Intent;
import android.content.res.Resources;
@@ -249,6 +250,15 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons {
RootsFragment.show(getSupportFragmentManager(),
/* includeApps= */ mState.action == ACTION_GET_CONTENT,
/* intent= */ moreApps);
+ if (useMaterial3()) {
+ View navRailRoots = findViewById(R.id.nav_rail_container_roots);
+ if (navRailRoots != null) {
+ // Medium layout, populate navigation rail layout.
+ RootsFragment.showNavRail(getSupportFragmentManager(),
+ /* includeApps= */ mState.action == ACTION_GET_CONTENT,
+ /* intent= */ moreApps);
+ }
+ }
}
}
diff --git a/src/com/android/documentsui/sidebar/AppItem.java b/src/com/android/documentsui/sidebar/AppItem.java
index b8abf8be9..c719241d2 100644
--- a/src/com/android/documentsui/sidebar/AppItem.java
+++ b/src/com/android/documentsui/sidebar/AppItem.java
@@ -26,6 +26,8 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.LayoutRes;
+
import com.android.documentsui.ActionHandler;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
@@ -43,7 +45,16 @@ public class AppItem extends Item {
private final ActionHandler mActionHandler;
public AppItem(ResolveInfo info, String title, UserId userId, ActionHandler actionHandler) {
- super(R.layout.item_root, title, getStringId(info), userId);
+ this(R.layout.item_root, info, title, userId, actionHandler);
+ }
+
+ public AppItem(
+ @LayoutRes int layoutId,
+ ResolveInfo info,
+ String title,
+ UserId userId,
+ ActionHandler actionHandler) {
+ super(layoutId, title, getStringId(info), userId);
this.info = info;
mActionHandler = actionHandler;
}
diff --git a/src/com/android/documentsui/sidebar/NavRailAppItem.java b/src/com/android/documentsui/sidebar/NavRailAppItem.java
new file mode 100644
index 000000000..befddf0aa
--- /dev/null
+++ b/src/com/android/documentsui/sidebar/NavRailAppItem.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.documentsui.sidebar;
+
+import android.content.pm.ResolveInfo;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.documentsui.ActionHandler;
+import com.android.documentsui.R;
+import com.android.documentsui.base.UserId;
+
+/**
+ * Similar to {@link AppItem} but only used in the navigation rail.
+ */
+public class NavRailAppItem extends AppItem {
+
+ public NavRailAppItem(
+ ResolveInfo info, String title, UserId userId, ActionHandler actionHandler) {
+ super(R.layout.nav_rail_item_root, info, title, userId, actionHandler);
+ }
+
+ @Override
+ public void bindView(View convertView) {
+ final ImageView icon = convertView.findViewById(android.R.id.icon);
+ final TextView titleView = convertView.findViewById(android.R.id.title);
+
+ titleView.setText(title);
+ titleView.setContentDescription(userId.getUserBadgedLabel(convertView.getContext(), title));
+
+ bindIcon(icon);
+ }
+}
diff --git a/src/com/android/documentsui/sidebar/NavRailProfileItem.java b/src/com/android/documentsui/sidebar/NavRailProfileItem.java
new file mode 100644
index 000000000..fe69c286f
--- /dev/null
+++ b/src/com/android/documentsui/sidebar/NavRailProfileItem.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.documentsui.sidebar;
+
+import android.content.pm.ResolveInfo;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.documentsui.ActionHandler;
+import com.android.documentsui.R;
+
+
+/**
+ * Similar to {@link ProfileItem} but only used in the navigation rail.
+ */
+public class NavRailProfileItem extends ProfileItem {
+
+ public NavRailProfileItem(ResolveInfo info, String title, ActionHandler actionHandler) {
+ super(R.layout.nav_rail_item_root, info, title, actionHandler);
+ }
+
+ @Override
+ public void bindView(View convertView) {
+ final ImageView icon = convertView.findViewById(android.R.id.icon);
+ final TextView titleView = convertView.findViewById(android.R.id.title);
+
+ titleView.setText(title);
+ titleView.setContentDescription(userId.getUserBadgedLabel(convertView.getContext(), title));
+
+ bindIcon(icon);
+ }
+}
diff --git a/src/com/android/documentsui/sidebar/NavRailRootAndAppItem.java b/src/com/android/documentsui/sidebar/NavRailRootAndAppItem.java
new file mode 100644
index 000000000..1bcc42f5c
--- /dev/null
+++ b/src/com/android/documentsui/sidebar/NavRailRootAndAppItem.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.documentsui.sidebar;
+
+import android.content.pm.ResolveInfo;
+import android.view.View;
+
+import com.android.documentsui.ActionHandler;
+import com.android.documentsui.R;
+import com.android.documentsui.base.RootInfo;
+
+/**
+ * Similar to {@link RootAndAppItem} but only used in the navigation rail.
+ */
+public class NavRailRootAndAppItem extends RootAndAppItem {
+
+ public NavRailRootAndAppItem(
+ RootInfo root, ResolveInfo info, ActionHandler actionHandler, boolean maybeShowBadge) {
+ super(R.layout.nav_rail_item_root, root, info, actionHandler, maybeShowBadge);
+ }
+
+ @Override
+ public void bindView(View convertView) {
+ bindIconAndTitle(convertView);
+ }
+}
diff --git a/src/com/android/documentsui/sidebar/NavRailRootItem.java b/src/com/android/documentsui/sidebar/NavRailRootItem.java
new file mode 100644
index 000000000..3d4042f22
--- /dev/null
+++ b/src/com/android/documentsui/sidebar/NavRailRootItem.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.documentsui.sidebar;
+
+
+import android.view.View;
+
+import com.android.documentsui.ActionHandler;
+import com.android.documentsui.R;
+import com.android.documentsui.base.RootInfo;
+
+/**
+ * Similar to {@link RootItem} but only used in the navigation rail.
+ */
+public class NavRailRootItem extends RootItem {
+
+ public NavRailRootItem(RootInfo root, ActionHandler actionHandler, boolean maybeShowBadge) {
+ super(
+ R.layout.nav_rail_item_root,
+ root,
+ actionHandler,
+ "" /* packageName */,
+ maybeShowBadge);
+ }
+
+ public NavRailRootItem(
+ RootInfo root,
+ ActionHandler actionHandler,
+ String packageName,
+ boolean maybeShowBadge) {
+ super(R.layout.nav_rail_item_root, root, actionHandler, packageName, maybeShowBadge);
+ }
+
+ @Override
+ public void bindView(View convertView) {
+ bindIconAndTitle(convertView);
+ }
+}
diff --git a/src/com/android/documentsui/sidebar/ProfileItem.java b/src/com/android/documentsui/sidebar/ProfileItem.java
index 15068ad4b..779f54445 100644
--- a/src/com/android/documentsui/sidebar/ProfileItem.java
+++ b/src/com/android/documentsui/sidebar/ProfileItem.java
@@ -20,6 +20,8 @@ import android.content.pm.ResolveInfo;
import android.view.View;
import android.widget.ImageView;
+import androidx.annotation.LayoutRes;
+
import com.android.documentsui.ActionHandler;
import com.android.documentsui.base.UserId;
@@ -32,6 +34,11 @@ class ProfileItem extends AppItem {
super(info, title, UserId.CURRENT_USER, actionHandler);
}
+ ProfileItem(
+ @LayoutRes int layoutId, ResolveInfo info, String title, ActionHandler actionHandler) {
+ super(layoutId, info, title, UserId.CURRENT_USER, actionHandler);
+ }
+
@Override
protected void bindIcon(ImageView icon) {
icon.setImageResource(com.android.documentsui.R.drawable.ic_user_profile);
diff --git a/src/com/android/documentsui/sidebar/RootAndAppItem.java b/src/com/android/documentsui/sidebar/RootAndAppItem.java
index b893878f3..8861f6058 100644
--- a/src/com/android/documentsui/sidebar/RootAndAppItem.java
+++ b/src/com/android/documentsui/sidebar/RootAndAppItem.java
@@ -18,11 +18,11 @@ package com.android.documentsui.sidebar;
import android.content.Context;
import android.content.pm.ResolveInfo;
-import android.os.UserManager;
import android.provider.DocumentsProvider;
-import android.text.TextUtils;
import android.view.View;
+import androidx.annotation.LayoutRes;
+
import com.android.documentsui.ActionHandler;
import com.android.documentsui.R;
import com.android.documentsui.base.RootInfo;
@@ -36,9 +36,18 @@ class RootAndAppItem extends RootItem {
public final ResolveInfo resolveInfo;
- public RootAndAppItem(RootInfo root, ResolveInfo info, ActionHandler actionHandler,
+ RootAndAppItem(
+ RootInfo root, ResolveInfo info, ActionHandler actionHandler, boolean maybeShowBadge) {
+ this(R.layout.item_root, root, info, actionHandler, maybeShowBadge);
+ }
+
+ RootAndAppItem(
+ @LayoutRes int layoutId,
+ RootInfo root,
+ ResolveInfo info,
+ ActionHandler actionHandler,
boolean maybeShowBadge) {
- super(root, actionHandler, info.activityInfo.packageName, maybeShowBadge);
+ super(layoutId, root, actionHandler, info.activityInfo.packageName, maybeShowBadge);
this.resolveInfo = info;
}
diff --git a/src/com/android/documentsui/sidebar/RootItem.java b/src/com/android/documentsui/sidebar/RootItem.java
index 4b40d91b3..326f086e1 100644
--- a/src/com/android/documentsui/sidebar/RootItem.java
+++ b/src/com/android/documentsui/sidebar/RootItem.java
@@ -30,6 +30,7 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import com.android.documentsui.ActionHandler;
@@ -64,7 +65,16 @@ public class RootItem extends Item {
public RootItem(RootInfo root, ActionHandler actionHandler, String packageName,
boolean maybeShowBadge) {
- super(R.layout.item_root, root.title, getStringId(root), root.userId);
+ this(R.layout.item_root, root, actionHandler, packageName, maybeShowBadge);
+ }
+
+ public RootItem(
+ @LayoutRes int layoutId,
+ RootInfo root,
+ ActionHandler actionHandler,
+ String packageName,
+ boolean maybeShowBadge) {
+ super(layoutId, root.title, getStringId(root), root.userId);
this.root = root;
mActionHandler = actionHandler;
mPackageName = packageName;
diff --git a/src/com/android/documentsui/sidebar/RootsFragment.java b/src/com/android/documentsui/sidebar/RootsFragment.java
index 76df696ab..2ec4c1728 100644
--- a/src/com/android/documentsui/sidebar/RootsFragment.java
+++ b/src/com/android/documentsui/sidebar/RootsFragment.java
@@ -19,6 +19,7 @@ package com.android.documentsui.sidebar;
import static com.android.documentsui.base.Shared.compareToIgnoreCaseNullable;
import static com.android.documentsui.base.SharedMinimal.DEBUG;
import static com.android.documentsui.base.SharedMinimal.VERBOSE;
+import static com.android.documentsui.flags.Flags.useMaterial3;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -49,6 +50,7 @@ import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
+import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
@@ -96,12 +98,23 @@ import java.util.stream.Collectors;
/**
* Display list of known storage backend roots.
+ * This fragment will be used in:
+ * * fixed_layout: as navigation tree (sidebar)
+ * * drawer_layout: as navigation drawer
+ * * nav_rail_layout: as navigation drawer and navigation rail.
*/
public class RootsFragment extends Fragment {
private static final String TAG = "RootsFragment";
private static final String EXTRA_INCLUDE_APPS = "includeApps";
private static final String EXTRA_INCLUDE_APPS_INTENT = "includeAppsIntent";
+ /**
+ * A key used to store the container id in the RootFragment.
+ * RootFragment is used in both navigation drawer and navigation rail, there are 2 instances
+ * of the fragment rendered on the page, we need to know which one is which to render different
+ * nav items inside.
+ */
+ private static final String EXTRA_CONTAINER_ID = "containerId";
private static final int CONTEXT_MENU_ITEM_TIMEOUT = 500;
private final OnItemClickListener mItemListener = new OnItemClickListener() {
@@ -135,41 +148,88 @@ public class RootsFragment extends Fragment {
private List<Item> mApplicationItemList;
+ // Weather the fragment is using nav_rail_container_roots as its container (in nav_rail_layout).
+ // This will always be false if useMaterial3() flag is off.
+ private boolean mUseRailAsContainer = false;
+
+ /**
+ * Show the RootsFragment inside the navigation drawer container.
+ */
+ public static RootsFragment show(FragmentManager fm, boolean includeApps, Intent intent) {
+ return showWithLayout(R.id.container_roots, fm, includeApps, intent);
+ }
+
+ /**
+ * Show the RootsFragment inside the navigation rail container.
+ */
+ public static RootsFragment showNavRail(FragmentManager fm, boolean includeApps,
+ Intent intent) {
+ return showWithLayout(R.id.nav_rail_container_roots, fm, includeApps, intent);
+ }
+
/**
* Shows the {@link RootsFragment}.
*
+ * @param containerId the container id where the {@link RootsFragment} will be rendered into
* @param fm the FragmentManager for interacting with fragments associated with this
* fragment's activity
* @param includeApps if {@code true}, query the intent from the system and include apps in
* the {@RootsFragment}.
* @param intent the intent to query for package manager
*/
- public static RootsFragment show(FragmentManager fm, boolean includeApps, Intent intent) {
+ private static RootsFragment showWithLayout(
+ @IdRes int containerId, FragmentManager fm, boolean includeApps, Intent intent) {
final Bundle args = new Bundle();
args.putBoolean(EXTRA_INCLUDE_APPS, includeApps);
args.putParcelable(EXTRA_INCLUDE_APPS_INTENT, intent);
+ if (useMaterial3()) {
+ args.putInt(EXTRA_CONTAINER_ID, containerId);
+ }
final RootsFragment fragment = new RootsFragment();
fragment.setArguments(args);
final FragmentTransaction ft = fm.beginTransaction();
- ft.replace(R.id.container_roots, fragment);
+ ft.replace(containerId, fragment);
ft.commitAllowingStateLoss();
return fragment;
}
+ /**
+ * Get the RootsFragment instance for the navigation drawer.
+ */
public static RootsFragment get(FragmentManager fm) {
return (RootsFragment) fm.findFragmentById(R.id.container_roots);
}
+ /**
+ * Get the RootsFragment instance for the navigation drawer.
+ */
+ public static RootsFragment getNavRail(FragmentManager fm) {
+ return (RootsFragment) fm.findFragmentById(R.id.nav_rail_container_roots);
+ }
+
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ if (useMaterial3()) {
+ mUseRailAsContainer =
+ getArguments() != null
+ && getArguments().getInt(EXTRA_CONTAINER_ID)
+ == R.id.nav_rail_container_roots;
+ }
+
mInjector = getBaseActivity().getInjector();
- final View view = inflater.inflate(R.layout.fragment_roots, container, false);
+ final View view =
+ inflater.inflate(
+ mUseRailAsContainer
+ ? R.layout.fragment_nav_rail_roots
+ : R.layout.fragment_roots,
+ container,
+ false);
mList = (ListView) view.findViewById(R.id.roots_list);
mList.setOnItemClickListener(mItemListener);
// ListView does not have right-click specific listeners, so we will have a
@@ -312,10 +372,17 @@ public class RootsFragment extends Fragment {
if (crossProfileResolveInfo != null && !Features.CROSS_PROFILE_TABS) {
// Add profile item if we don't support cross-profile tab.
sortedItems.add(new SpacerItem());
- sortedItems.add(new ProfileItem(crossProfileResolveInfo,
- crossProfileResolveInfo.loadLabel(
- getContext().getPackageManager()).toString(),
- mActionHandler));
+ if (mUseRailAsContainer) {
+ sortedItems.add(new NavRailProfileItem(crossProfileResolveInfo,
+ crossProfileResolveInfo.loadLabel(
+ getContext().getPackageManager()).toString(),
+ mActionHandler));
+ } else {
+ sortedItems.add(new ProfileItem(crossProfileResolveInfo,
+ crossProfileResolveInfo.loadLabel(
+ getContext().getPackageManager()).toString(),
+ mActionHandler));
+ }
}
// Disable drawer if only one root
@@ -414,15 +481,30 @@ public class RootsFragment extends Fragment {
if (root.isExternalStorageHome()) {
continue;
} else if (root.isLibrary() || root.isDownloads()) {
- item = new RootItem(root, mActionHandler, maybeShowBadge);
+ item =
+ mUseRailAsContainer
+ ? new NavRailRootItem(root, mActionHandler, maybeShowBadge)
+ : new RootItem(root, mActionHandler, maybeShowBadge);
librariesBuilder.add(item);
} else if (root.isStorage()) {
- item = new RootItem(root, mActionHandler, maybeShowBadge);
+ item =
+ mUseRailAsContainer
+ ? new NavRailRootItem(root, mActionHandler, maybeShowBadge)
+ : new RootItem(root, mActionHandler, maybeShowBadge);
storageProvidersBuilder.add(item);
} else {
- item = new RootItem(root, mActionHandler,
- providersAccess.getPackageName(root.userId, root.authority),
- maybeShowBadge);
+ item =
+ mUseRailAsContainer
+ ? new NavRailRootItem(
+ root,
+ mActionHandler,
+ providersAccess.getPackageName(root.userId, root.authority),
+ maybeShowBadge)
+ : new RootItem(
+ root,
+ mActionHandler,
+ providersAccess.getPackageName(root.userId, root.authority),
+ maybeShowBadge);
otherProviders.add(item);
}
}
@@ -566,8 +648,18 @@ public class RootsFragment extends Fragment {
appsMapping.put(userPackage, info);
if (!CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) {
- final Item item = new AppItem(info, info.loadLabel(pm).toString(), userId,
- mActionHandler);
+ final Item item =
+ mUseRailAsContainer
+ ? new NavRailAppItem(
+ info,
+ info.loadLabel(pm).toString(),
+ userId,
+ mActionHandler)
+ : new AppItem(
+ info,
+ info.loadLabel(pm).toString(),
+ userId,
+ mActionHandler);
appItems.put(userPackage, item);
if (VERBOSE) Log.v(TAG, "Adding handler app: " + item);
}
@@ -583,8 +675,12 @@ public class RootsFragment extends Fragment {
final Item item;
if (resolveInfo != null) {
- item = new RootAndAppItem(rootItem.root, resolveInfo, mActionHandler,
- maybeShowBadge);
+ item =
+ mUseRailAsContainer
+ ? new NavRailRootAndAppItem(
+ rootItem.root, resolveInfo, mActionHandler, maybeShowBadge)
+ : new RootAndAppItem(
+ rootItem.root, resolveInfo, mActionHandler, maybeShowBadge);
appItems.remove(userPackage);
} else {
item = rootItem;