From a37002876eaf1830fec276e6ed460704c7106d8b Mon Sep 17 00:00:00 2001 From: Rohit Verma Date: Tue, 12 Aug 2025 00:12:44 +0530 Subject: [PATCH] feat(customselector): improve RecyclerView edge-to-edge inset handling It allows the last item to sits above the navigation bar while preserving edge-to-edge appearance. --- .../ui/selector/CustomSelectorActivity.kt | 6 ++-- .../ui/selector/FolderFragment.kt | 2 ++ .../ui/selector/ImageFragment.kt | 2 ++ .../free/nrw/commons/utils/EdgeToEdgeUtils.kt | 33 +++++++++++++++++++ .../res/layout/fragment_custom_selector.xml | 1 + 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt index fd2987c97..2761ce5e4 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt @@ -54,9 +54,10 @@ import fr.free.nrw.commons.databinding.CustomSelectorBottomLayoutBinding import fr.free.nrw.commons.databinding.CustomSelectorToolbarBinding import fr.free.nrw.commons.media.ZoomableActivity import fr.free.nrw.commons.theme.BaseActivity -import fr.free.nrw.commons.utils.applyEdgeToEdgeAllInsets import fr.free.nrw.commons.upload.FileUtilsWrapper import fr.free.nrw.commons.utils.CustomSelectorUtils +import fr.free.nrw.commons.utils.applyEdgeToEdgeBottomPaddingInsets +import fr.free.nrw.commons.utils.applyEdgeToEdgeTopInsets import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -199,7 +200,8 @@ class CustomSelectorActivity : .fillMaxWidth(), ) } - applyEdgeToEdgeAllInsets(binding.root) + applyEdgeToEdgeTopInsets(toolbarBinding.toolbarLayout) + bottomSheetBinding.bottomLayout.applyEdgeToEdgeBottomPaddingInsets() val view = binding.root setContentView(view) diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt index 6ca2b06e4..0c3c5bdd0 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt @@ -18,6 +18,7 @@ import fr.free.nrw.commons.databinding.FragmentCustomSelectorBinding import fr.free.nrw.commons.di.CommonsDaggerSupportFragment import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.upload.FileProcessor +import fr.free.nrw.commons.utils.applyEdgeToEdgeBottomPaddingInsets import javax.inject.Inject /** @@ -99,6 +100,7 @@ class FolderFragment : CommonsDaggerSupportFragment() { selectorRV = binding?.selectorRv loader = binding?.loader with(binding?.selectorRv) { + this?.applyEdgeToEdgeBottomPaddingInsets() this?.layoutManager = gridLayoutManager this?.setHasFixedSize(true) this?.adapter = folderAdapter diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt index 6e08e30f1..4f37106cc 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt @@ -41,6 +41,7 @@ import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.theme.BaseActivity import fr.free.nrw.commons.upload.FileProcessor import fr.free.nrw.commons.upload.FileUtilsWrapper +import fr.free.nrw.commons.utils.applyEdgeToEdgeBottomPaddingInsets import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -217,6 +218,7 @@ class ImageFragment : imageAdapter.setSingleSelection(singleSelection) gridLayoutManager = GridLayoutManager(context, getSpanCount()) with(binding?.selectorRv) { + this?.applyEdgeToEdgeBottomPaddingInsets() this?.layoutManager = gridLayoutManager this?.setHasFixedSize(true) this?.adapter = imageAdapter diff --git a/app/src/main/java/fr/free/nrw/commons/utils/EdgeToEdgeUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/EdgeToEdgeUtils.kt index e3209c00a..9a5460c46 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/EdgeToEdgeUtils.kt +++ b/app/src/main/java/fr/free/nrw/commons/utils/EdgeToEdgeUtils.kt @@ -9,6 +9,7 @@ import androidx.core.view.marginLeft import androidx.core.view.marginRight import androidx.core.view.marginTop import androidx.core.view.updateLayoutParams +import androidx.core.view.updatePadding import fr.free.nrw.commons.R fun View.applyEdgeToEdgeInsets( @@ -65,6 +66,38 @@ fun View.applyEdgeToEdgeInsets( } } +fun View.applyEdgeToEdgeTopPaddingInsets( + typeMask: Int = WindowInsetsCompat.Type.systemBars(), +) { + ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets -> + val insets = windowInsets.getInsets(typeMask) + + view.updatePadding( + left = insets.left, + right = insets.right, + top = insets.top + ) + + WindowInsetsCompat.CONSUMED + } +} + +fun View.applyEdgeToEdgeBottomPaddingInsets( + typeMask: Int = WindowInsetsCompat.Type.systemBars(), +) { + ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets -> + val insets = windowInsets.getInsets(typeMask) + + view.updatePadding( + left = insets.left, + right = insets.right, + bottom = insets.bottom + ) + + WindowInsetsCompat.CONSUMED + } +} + fun applyEdgeToEdgeAllInsets(view: View) = view.applyEdgeToEdgeInsets { insets -> leftMargin = insets.left rightMargin = insets.right diff --git a/app/src/main/res/layout/fragment_custom_selector.xml b/app/src/main/res/layout/fragment_custom_selector.xml index 03381fd24..b016b6605 100644 --- a/app/src/main/res/layout/fragment_custom_selector.xml +++ b/app/src/main/res/layout/fragment_custom_selector.xml @@ -34,6 +34,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/switchWidget" + android:clipToPadding="false" />