summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Govinda Wasserman <gwasserman@google.com> 2024-07-24 21:36:22 -0400
committer Govinda Wasserman <gwasserman@google.com> 2024-07-25 16:02:17 -0400
commit068c395fd118c20632a5a77a0e28639863dc070b (patch)
tree59cc336f64bbe0da15f3db048ded9b72646b0b55 /java/src
parent8cec6eefb3607d8ba666ffdecb833792efa3672b (diff)
Center initial item in Sharousel
As long as there are enough items in the row to center the initial item, it will be centered, otherwise it will be as close to center as the scroll bounds allow. Test: manual testing BUG: 341925364 Flag: android.service.chooser.chooser_payload_toggling Change-Id: Ifb96071ba70c3ba42f53d584ddfc31d4fc62cedf
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt100
1 files changed, 67 insertions, 33 deletions
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
index 9ac36a87..e40d98bd 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
@@ -45,6 +45,7 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -71,6 +72,7 @@ import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.Prev
import com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel.ShareouselPreviewViewModel
import com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel.ShareouselViewModel
import kotlin.math.abs
+import kotlin.math.min
import kotlinx.coroutines.launch
@Composable
@@ -104,44 +106,48 @@ private fun PreviewCarousel(
previews: PreviewsModel,
viewModel: ShareouselViewModel,
) {
- val centerIdx = previews.startIdx
- val carouselState =
- rememberLazyListState(
- initialFirstVisibleItemIndex = centerIdx,
- prefetchStrategy = remember { ShareouselLazyListPrefetchStrategy() }
- )
var maxAspectRatio by remember { mutableStateOf(0f) }
var viewportHeight by remember { mutableStateOf(0) }
-
- val horizontalPadding = 16.dp
+ var viewportCenter by remember { mutableStateOf(0) }
+ var horizontalPadding by remember { mutableStateOf(0.dp) }
Box(
modifier =
Modifier.fillMaxWidth()
.height(dimensionResource(R.dimen.chooser_preview_image_height_tall))
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
- val aspectRatio =
+ val (minItemWidth, maxAR) =
if (placeable.height <= 0) {
- 0f
+ 0f to 0f
} else {
- val maxItemWidth =
- maxOf(0, placeable.width - 2 * horizontalPadding.roundToPx())
- (maxItemWidth.toFloat() / placeable.height).coerceIn(
- 0f,
- MAX_ASPECT_RATIO
- )
+ val minItemWidth = (MIN_ASPECT_RATIO * placeable.height)
+ val maxItemWidth = maxOf(0, placeable.width - 32.dp.roundToPx())
+ val maxAR =
+ (maxItemWidth.toFloat() / placeable.height).coerceIn(
+ 0f,
+ MAX_ASPECT_RATIO
+ )
+ minItemWidth to maxAR
}
- maxAspectRatio = aspectRatio
+ viewportCenter = placeable.width / 2
+ maxAspectRatio = maxAR
viewportHeight = placeable.height
+ horizontalPadding = ((placeable.width - minItemWidth) / 2).toDp()
layout(placeable.width, placeable.height) { placeable.place(0, 0) }
},
) {
- if (maxAspectRatio <= 0) {
+ if (maxAspectRatio <= 0 && previews.previewModels.isNotEmpty()) {
// Do not compose the list until we know the viewport size
return@Box
}
- // TODO: start item needs to be centered, check out ScalingLazyColumn impl or see if
- // HorizontalPager works for our use-case
+
+ var firstSelectedIndex by remember { mutableStateOf(null as Int?) }
+
+ val carouselState =
+ rememberLazyListState(
+ prefetchStrategy = remember { ShareouselLazyListPrefetchStrategy() },
+ )
+
LazyRow(
state = carouselState,
horizontalArrangement = Arrangement.spacedBy(4.dp),
@@ -149,26 +155,38 @@ private fun PreviewCarousel(
modifier = Modifier.fillMaxSize().systemGestureExclusion(),
) {
itemsIndexed(previews.previewModels, key = { _, model -> model.uri }) { index, model ->
+ val visibleItem by remember {
+ derivedStateOf {
+ carouselState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index }
+ }
+ }
+
// Index if this is the element in the center of the viewing area, otherwise null
val previewIndex by remember {
derivedStateOf {
- carouselState.layoutInfo.visibleItemsInfo
- .firstOrNull { it.index == index }
- ?.let {
- val viewportCenter = carouselState.layoutInfo.viewportEndOffset / 2
- val halfPreviewWidth = it.size / 2
- val previewCenter = it.offset + halfPreviewWidth
- val previewDistanceToViewportCenter =
- abs(previewCenter - viewportCenter)
- if (previewDistanceToViewportCenter <= halfPreviewWidth) {
- index
- } else {
- null
- }
+ visibleItem?.let {
+ val halfPreviewWidth = it.size / 2
+ val previewCenter = it.offset + halfPreviewWidth
+ val previewDistanceToViewportCenter =
+ abs(previewCenter - viewportCenter)
+ if (previewDistanceToViewportCenter <= halfPreviewWidth) {
+ index
+ } else {
+ null
}
+ }
}
}
+ val previewModel =
+ viewModel.preview(model, viewportHeight, previewIndex, rememberCoroutineScope())
+ val selected by
+ previewModel.isSelected.collectAsStateWithLifecycle(initialValue = false)
+
+ if (selected) {
+ firstSelectedIndex = min(index, firstSelectedIndex ?: Int.MAX_VALUE)
+ }
+
ShareouselCard(
viewModel.preview(
model,
@@ -180,6 +198,22 @@ private fun PreviewCarousel(
)
}
}
+
+ firstSelectedIndex?.let { index ->
+ LaunchedEffect(Unit) {
+ val visibleItem =
+ carouselState.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index }
+ val center =
+ with(carouselState.layoutInfo) {
+ ((viewportEndOffset - viewportStartOffset) / 2) + viewportStartOffset
+ }
+
+ carouselState.scrollToItem(
+ index = index,
+ scrollOffset = visibleItem?.size?.div(2)?.minus(center) ?: 0,
+ )
+ }
+ }
}
}