Loading res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml +1 −4 Original line number Diff line number Diff line Loading @@ -22,10 +22,7 @@ android:layout_margin="@dimen/grid_item_margin" android:clickable="true" android:defaultFocusHighlightEnabled="false" android:focusable="true" android:paddingEnd="@dimen/grid_item_padding_end" android:paddingStart="@dimen/grid_item_padding_start" android:paddingTop="@dimen/grid_item_padding_top"> android:focusable="true"> <!-- Main item thumbnail. Comprised of two overlapping images, the visibility of which is controlled by code in Loading res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ <dimen name="toolbar_padding_start">@dimen/main_container_padding_start</dimen> <dimen name="grid_container_padding_left">@dimen/space_small_4</dimen> <dimen name="grid_container_padding_top">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_right">@dimen/space_small_4</dimen> <dimen name="grid_container_padding_bottom">@dimen/space_extra_small_4</dimen> <dimen name="list_container_padding">@dimen/space_extra_small_6</dimen> <!-- list_container_padding + list_item_padding_start --> Loading res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml +7 −6 Original line number Diff line number Diff line Loading @@ -43,10 +43,14 @@ <dimen name="progress_bar_height">4dp</dimen> <fraction name="grid_scale_min">85%</fraction> <fraction name="grid_scale_max">200%</fraction> <dimen name="grid_width">150dp</dimen> <dimen name="grid_height">132dp</dimen> <dimen name="grid_width">144dp</dimen> <dimen name="grid_height">116dp</dimen> <dimen name="grid_section_separator_height">0dp</dimen> <dimen name="grid_item_margin">@dimen/space_small_1</dimen> <dimen name="grid_item_margin">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_left">@dimen/space_small_1</dimen> <dimen name="grid_container_padding_top">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_right">@dimen/space_small_1</dimen> <dimen name="grid_container_padding_bottom">@dimen/space_extra_small_4</dimen> <dimen name="grid_padding_horiz">4dp</dimen> <dimen name="grid_padding_vert">4dp</dimen> <dimen name="list_item_height">56dp</dimen> Loading @@ -72,9 +76,6 @@ <dimen name="breadcrumb_item_arrow_size">16dp</dimen> <dimen name="dir_elevation">8dp</dimen> <dimen name="drag_shadow_size">120dp</dimen> <dimen name="grid_item_padding_start">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_padding_end">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_padding_top">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_thumbnail_width">80dp</dimen> <dimen name="grid_item_thumbnail_height">80dp</dimen> <dimen name="grid_item_thumbnail_radius">12dp</dimen> Loading src/com/android/documentsui/dirlist/DirectoryFragment.java +61 −7 Original line number Diff line number Diff line Loading @@ -193,6 +193,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On private IconHelper mIconHelper; private SwipeRefreshLayout mRefreshLayout; private RecyclerView mRecView; private GridEvenSpacingDecoration mGridEvenSpacingDecoration; private DocumentsAdapter mAdapter; private DocumentClipper mClipper; private GridLayoutManager mLayout; Loading Loading @@ -525,6 +526,14 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mState = mActivity.getDisplayState(); if (isUseMaterial3FlagEnabled()) { mGridEvenSpacingDecoration = new GridEvenSpacingDecoration(); if (mState.derivedMode == MODE_GRID) { // Ensure items are spaced evenly in the grid layout. mRecView.addItemDecoration(mGridEvenSpacingDecoration); } } // Read arguments when object created for the first time. // Restore state if fragment recreated. Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState; Loading Loading @@ -810,6 +819,15 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On } public void onViewModeChanged() { if (isUseMaterial3FlagEnabled()) { // Only enable the decoration for grid mode. if (mState.derivedMode != MODE_GRID) { mRecView.removeItemDecoration(mGridEvenSpacingDecoration); } else { mRecView.addItemDecoration(mGridEvenSpacingDecoration); } } // Mode change is just visual change; no need to kick loader. mRootView.announceForAccessibility(getString( mState.derivedMode == State.MODE_GRID ? R.string.grid_mode_showing Loading @@ -829,15 +847,51 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On */ private void updateLayout(@ViewMode int mode) { mMode = mode; mAppBarHeight = getAppBarLayoutHeight(); mSaveLayoutHeight = getSaveLayoutHeight(); if (isUseMaterial3FlagEnabled()) { if (mode == MODE_GRID) { int itemMarg = getResources().getDimensionPixelSize(R.dimen.grid_item_margin); // Subtract the item's margin since we don't want to double count the margin in the // distance between the outer grid items and the grid boundary. int leftPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_left) - itemMarg; int topPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_top) - itemMarg; int rightPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_right) - itemMarg; int botPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_bottom) - itemMarg; mRecView.setPadding(leftPad, topPad + mAppBarHeight, rightPad, botPad + mSaveLayoutHeight); } else { int pad = getDirectoryPadding(mode); mRecView.setPadding(pad, mAppBarHeight, pad, mSaveLayoutHeight); } mColumnCount = calculateColumnCount(mode); if (mLayout != null) { mLayout.setSpanCount(mColumnCount); } } else { mColumnCount = calculateColumnCount(mode); if (mLayout != null) { mLayout.setSpanCount(mColumnCount); } int pad = getDirectoryPadding(mode); mAppBarHeight = getAppBarLayoutHeight(); mSaveLayoutHeight = getSaveLayoutHeight(); mRecView.setPadding(pad, mAppBarHeight, pad, mSaveLayoutHeight); } if (isUseMaterial3FlagEnabled() && mRecView.getItemDecorationCount() > 0) { // Invalidate item decorations so they are recalculated before layout. This also // calls requestLayout(). mRecView.invalidateItemDecorations(); } else { mRecView.requestLayout(); } mIconHelper.setViewMode(mode); int range = getResources().getDimensionPixelOffset(R.dimen.refresh_icon_range); Loading src/com/android/documentsui/dirlist/GridEvenSpacingDecoration.java 0 → 100644 +63 −0 Original line number Diff line number Diff line /* * 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. */ package com.android.documentsui.dirlist; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; /** * RecyclerView ItemDecorator that distributes the horizontal space into equal size buckets * for each item (to match the bounds given by the GridViewLayout) and adds an offset to * either side to centre the item within its bucket. This only works when the layout manager * is GridViewLayout and all items have the same fixed width. */ public class GridEvenSpacingDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (!isUseMaterial3FlagEnabled()) { return; } RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (!(layoutManager instanceof GridLayoutManager)) { return; } ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT || lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) { // This item does not have a fixed width. return; } // Distribute the horizontal space into equal size buckets for each item and add an // offset to either side to centre the item within its bucket. int spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); int itemWidth = lp.getMarginStart() + lp.width + lp.getMarginEnd(); int allocatedGridSpace = (parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight()) / spanCount; int extraSpace = allocatedGridSpace - itemWidth; int offset = extraSpace / 2; outRect.left = offset; outRect.right = offset; } } Loading
res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml +1 −4 Original line number Diff line number Diff line Loading @@ -22,10 +22,7 @@ android:layout_margin="@dimen/grid_item_margin" android:clickable="true" android:defaultFocusHighlightEnabled="false" android:focusable="true" android:paddingEnd="@dimen/grid_item_padding_end" android:paddingStart="@dimen/grid_item_padding_start" android:paddingTop="@dimen/grid_item_padding_top"> android:focusable="true"> <!-- Main item thumbnail. Comprised of two overlapping images, the visibility of which is controlled by code in Loading
res/flag(com.android.documentsui.flags.use_material3)/values-w600dp/dimens.xml +5 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,11 @@ <dimen name="toolbar_padding_start">@dimen/main_container_padding_start</dimen> <dimen name="grid_container_padding_left">@dimen/space_small_4</dimen> <dimen name="grid_container_padding_top">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_right">@dimen/space_small_4</dimen> <dimen name="grid_container_padding_bottom">@dimen/space_extra_small_4</dimen> <dimen name="list_container_padding">@dimen/space_extra_small_6</dimen> <!-- list_container_padding + list_item_padding_start --> Loading
res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml +7 −6 Original line number Diff line number Diff line Loading @@ -43,10 +43,14 @@ <dimen name="progress_bar_height">4dp</dimen> <fraction name="grid_scale_min">85%</fraction> <fraction name="grid_scale_max">200%</fraction> <dimen name="grid_width">150dp</dimen> <dimen name="grid_height">132dp</dimen> <dimen name="grid_width">144dp</dimen> <dimen name="grid_height">116dp</dimen> <dimen name="grid_section_separator_height">0dp</dimen> <dimen name="grid_item_margin">@dimen/space_small_1</dimen> <dimen name="grid_item_margin">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_left">@dimen/space_small_1</dimen> <dimen name="grid_container_padding_top">@dimen/space_extra_small_4</dimen> <dimen name="grid_container_padding_right">@dimen/space_small_1</dimen> <dimen name="grid_container_padding_bottom">@dimen/space_extra_small_4</dimen> <dimen name="grid_padding_horiz">4dp</dimen> <dimen name="grid_padding_vert">4dp</dimen> <dimen name="list_item_height">56dp</dimen> Loading @@ -72,9 +76,6 @@ <dimen name="breadcrumb_item_arrow_size">16dp</dimen> <dimen name="dir_elevation">8dp</dimen> <dimen name="drag_shadow_size">120dp</dimen> <dimen name="grid_item_padding_start">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_padding_end">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_padding_top">@dimen/space_extra_small_2</dimen> <dimen name="grid_item_thumbnail_width">80dp</dimen> <dimen name="grid_item_thumbnail_height">80dp</dimen> <dimen name="grid_item_thumbnail_radius">12dp</dimen> Loading
src/com/android/documentsui/dirlist/DirectoryFragment.java +61 −7 Original line number Diff line number Diff line Loading @@ -193,6 +193,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On private IconHelper mIconHelper; private SwipeRefreshLayout mRefreshLayout; private RecyclerView mRecView; private GridEvenSpacingDecoration mGridEvenSpacingDecoration; private DocumentsAdapter mAdapter; private DocumentClipper mClipper; private GridLayoutManager mLayout; Loading Loading @@ -525,6 +526,14 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mState = mActivity.getDisplayState(); if (isUseMaterial3FlagEnabled()) { mGridEvenSpacingDecoration = new GridEvenSpacingDecoration(); if (mState.derivedMode == MODE_GRID) { // Ensure items are spaced evenly in the grid layout. mRecView.addItemDecoration(mGridEvenSpacingDecoration); } } // Read arguments when object created for the first time. // Restore state if fragment recreated. Bundle args = savedInstanceState == null ? getArguments() : savedInstanceState; Loading Loading @@ -810,6 +819,15 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On } public void onViewModeChanged() { if (isUseMaterial3FlagEnabled()) { // Only enable the decoration for grid mode. if (mState.derivedMode != MODE_GRID) { mRecView.removeItemDecoration(mGridEvenSpacingDecoration); } else { mRecView.addItemDecoration(mGridEvenSpacingDecoration); } } // Mode change is just visual change; no need to kick loader. mRootView.announceForAccessibility(getString( mState.derivedMode == State.MODE_GRID ? R.string.grid_mode_showing Loading @@ -829,15 +847,51 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On */ private void updateLayout(@ViewMode int mode) { mMode = mode; mAppBarHeight = getAppBarLayoutHeight(); mSaveLayoutHeight = getSaveLayoutHeight(); if (isUseMaterial3FlagEnabled()) { if (mode == MODE_GRID) { int itemMarg = getResources().getDimensionPixelSize(R.dimen.grid_item_margin); // Subtract the item's margin since we don't want to double count the margin in the // distance between the outer grid items and the grid boundary. int leftPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_left) - itemMarg; int topPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_top) - itemMarg; int rightPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_right) - itemMarg; int botPad = getResources().getDimensionPixelSize( R.dimen.grid_container_padding_bottom) - itemMarg; mRecView.setPadding(leftPad, topPad + mAppBarHeight, rightPad, botPad + mSaveLayoutHeight); } else { int pad = getDirectoryPadding(mode); mRecView.setPadding(pad, mAppBarHeight, pad, mSaveLayoutHeight); } mColumnCount = calculateColumnCount(mode); if (mLayout != null) { mLayout.setSpanCount(mColumnCount); } } else { mColumnCount = calculateColumnCount(mode); if (mLayout != null) { mLayout.setSpanCount(mColumnCount); } int pad = getDirectoryPadding(mode); mAppBarHeight = getAppBarLayoutHeight(); mSaveLayoutHeight = getSaveLayoutHeight(); mRecView.setPadding(pad, mAppBarHeight, pad, mSaveLayoutHeight); } if (isUseMaterial3FlagEnabled() && mRecView.getItemDecorationCount() > 0) { // Invalidate item decorations so they are recalculated before layout. This also // calls requestLayout(). mRecView.invalidateItemDecorations(); } else { mRecView.requestLayout(); } mIconHelper.setViewMode(mode); int range = getResources().getDimensionPixelOffset(R.dimen.refresh_icon_range); Loading
src/com/android/documentsui/dirlist/GridEvenSpacingDecoration.java 0 → 100644 +63 −0 Original line number Diff line number Diff line /* * 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. */ package com.android.documentsui.dirlist; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import android.graphics.Rect; import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; /** * RecyclerView ItemDecorator that distributes the horizontal space into equal size buckets * for each item (to match the bounds given by the GridViewLayout) and adds an offset to * either side to centre the item within its bucket. This only works when the layout manager * is GridViewLayout and all items have the same fixed width. */ public class GridEvenSpacingDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (!isUseMaterial3FlagEnabled()) { return; } RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); if (!(layoutManager instanceof GridLayoutManager)) { return; } ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT || lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) { // This item does not have a fixed width. return; } // Distribute the horizontal space into equal size buckets for each item and add an // offset to either side to centre the item within its bucket. int spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); int itemWidth = lp.getMarginStart() + lp.width + lp.getMarginEnd(); int allocatedGridSpace = (parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight()) / spanCount; int extraSpace = allocatedGridSpace - itemWidth; int offset = extraSpace / 2; outRect.left = offset; outRect.right = offset; } }