diff options
| author | 2024-07-24 21:36:22 -0400 | |
|---|---|---|
| committer | 2024-07-25 16:02:17 -0400 | |
| commit | 068c395fd118c20632a5a77a0e28639863dc070b (patch) | |
| tree | 59cc336f64bbe0da15f3db048ded9b72646b0b55 /java/src | |
| parent | 8cec6eefb3607d8ba666ffdecb833792efa3672b (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.kt | 100 |
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, + ) + } + } } } |