diff options
author | 2024-12-19 14:44:29 -0500 | |
---|---|---|
committer | 2024-12-20 09:47:40 -0500 | |
commit | 12540dff41da461eea512e8a320bd87c286a7fbb (patch) | |
tree | cdbe4c77369dcb55713baeef268297d4d7ad8a23 /java | |
parent | 4097639cf7ea07055b86c3e65bd8c09b89ef25c9 (diff) |
Add select/unselect visual cue to Shareousel
When an item is selected it will shrink and when it is unselected it
will grow back to the standard size. This provides improved visual
confirmation of the selected state of items.
Test: Manual test using Photos or ShareTest
BUG: 361792274
Flag: com.android.intentresolver.shareousel_selection_shrink
Change-Id: I7f5ca60d584900fc5e2ba0d479ecc0f2e624b367
Diffstat (limited to 'java')
-rw-r--r-- | java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt | 90 |
1 files changed, 53 insertions, 37 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 c51021a8..9bc8d3e2 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 @@ -16,6 +16,7 @@ package com.android.intentresolver.contentpreview.payloadtoggle.ui.composable import androidx.compose.animation.Crossfade +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -52,8 +53,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale @@ -68,6 +71,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.intentresolver.Flags.shareouselScrollOffscreenSelections +import com.android.intentresolver.Flags.shareouselSelectionShrink import com.android.intentresolver.Flags.unselectFinalItem import com.android.intentresolver.R import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate @@ -247,43 +251,52 @@ private fun ShareouselCard(viewModel: ShareouselPreviewViewModel, aspectRatio: F ContentType.Video -> stringResource(R.string.selectable_video) else -> stringResource(R.string.selectable_item) } - Crossfade( - targetState = bitmapLoadState, - modifier = - Modifier.semantics { this.contentDescription = contentDescription } - .clip(RoundedCornerShape(size = 12.dp)) - .toggleable( - value = selected, - onValueChange = { scope.launch { viewModel.setSelected(it) } }, - ), - ) { state -> - if (state is ValueUpdate.Value) { - state.getOrDefault(null).let { bitmap -> - ShareouselCard( - image = { - bitmap?.let { - Image( - bitmap = bitmap.asImageBitmap(), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.aspectRatio(aspectRatio), - ) - } ?: PlaceholderBox(aspectRatio) - }, - contentType = viewModel.contentType, - selected = selected, - modifier = - Modifier.thenIf(selected) { - Modifier.border( - width = 4.dp, - color = borderColor, - shape = RoundedCornerShape(size = 12.dp), - ) + Box( + modifier = Modifier.fillMaxHeight().aspectRatio(aspectRatio), + contentAlignment = Alignment.Center, + ) { + Crossfade( + targetState = bitmapLoadState, + modifier = + Modifier.semantics { this.contentDescription = contentDescription } + .toggleable( + value = selected, + onValueChange = { scope.launch { viewModel.setSelected(it) } }, + ) + .conditional(shareouselSelectionShrink()) { + val selectionScale by animateFloatAsState(if (selected) 0.95f else 1f) + scale(selectionScale) + } + .clip(RoundedCornerShape(size = 12.dp)), + ) { state -> + if (state is ValueUpdate.Value) { + state.getOrDefault(null).let { bitmap -> + ShareouselCard( + image = { + bitmap?.let { + Image( + bitmap = bitmap.asImageBitmap(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.aspectRatio(aspectRatio), + ) + } ?: PlaceholderBox(aspectRatio) }, - ) + contentType = viewModel.contentType, + selected = selected, + modifier = + Modifier.conditional(selected) { + border( + width = 4.dp, + color = borderColor, + shape = RoundedCornerShape(size = 12.dp), + ) + }, + ) + } + } else { + PlaceholderBox(aspectRatio) } - } else { - PlaceholderBox(aspectRatio) } } } @@ -370,8 +383,11 @@ private fun ShareouselAction( ) } -inline fun Modifier.thenIf(condition: Boolean, crossinline factory: () -> Modifier): Modifier = - if (condition) this.then(factory()) else this +@Composable +private inline fun Modifier.conditional( + condition: Boolean, + crossinline whenTrue: @Composable Modifier.() -> Modifier, +): Modifier = if (condition) this.whenTrue() else this private data class PreviewCarouselMeasurements( val viewportHeightPx: Int, |