diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt index 17095ca55..59dbbc2f2 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt @@ -27,13 +27,18 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text @@ -80,22 +85,18 @@ import com.google.jetpackcamera.model.StreamConfig import com.google.jetpackcamera.model.TestPattern import com.google.jetpackcamera.model.VideoCaptureEvent import com.google.jetpackcamera.ui.components.capture.AmplitudeToggleButton -import com.google.jetpackcamera.ui.components.capture.CAPTURE_MODE_TOGGLE_BUTTON import com.google.jetpackcamera.ui.components.capture.CaptureButton +import com.google.jetpackcamera.ui.components.capture.CaptureLayout import com.google.jetpackcamera.ui.components.capture.CaptureModeToggleButton -import com.google.jetpackcamera.ui.components.capture.ELAPSED_TIME_TAG import com.google.jetpackcamera.ui.components.capture.ElapsedTimeText -import com.google.jetpackcamera.ui.components.capture.FLIP_CAMERA_BUTTON import com.google.jetpackcamera.ui.components.capture.FlipCameraButton import com.google.jetpackcamera.ui.components.capture.ImageWell import com.google.jetpackcamera.ui.components.capture.PauseResumeToggleButton import com.google.jetpackcamera.ui.components.capture.PreviewDisplay -import com.google.jetpackcamera.ui.components.capture.PreviewLayout import com.google.jetpackcamera.ui.components.capture.R import com.google.jetpackcamera.ui.components.capture.ScreenFlashScreen import com.google.jetpackcamera.ui.components.capture.StabilizationIcon import com.google.jetpackcamera.ui.components.capture.TestableSnackbar -import com.google.jetpackcamera.ui.components.capture.VIDEO_QUALITY_TAG import com.google.jetpackcamera.ui.components.capture.VideoQualityIcon import com.google.jetpackcamera.ui.components.capture.ZoomButtonRow import com.google.jetpackcamera.ui.components.capture.ZoomState @@ -185,7 +186,7 @@ fun PreviewScreen( } when (val currentUiState = captureUiState) { - is CaptureUiState.NotReady -> LoadingScreen() + is CaptureUiState.NotReady -> LoadingCaptureScreen() is CaptureUiState.Ready -> { var initialRecordingSettings by remember { mutableStateOf( @@ -351,7 +352,7 @@ fun PreviewScreen( } } -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable private fun ContentScreen( captureUiState: CaptureUiState.Ready, @@ -410,7 +411,7 @@ private fun ContentScreen( } } - LayoutWrapper( + CaptureLayoutWrapper( modifier = modifier, hdrIndicator = { HdrIndicator(modifier = it, hdrUiState = captureUiState.hdrUiState) }, flashModeIndicator = { @@ -421,8 +422,8 @@ private fun ContentScreen( }, videoQualityIndicator = { VideoQualityIcon( - captureUiState.videoQuality, - Modifier.testTag(VIDEO_QUALITY_TAG) + modifier = it, + videoQuality = captureUiState.videoQuality ) }, stabilizationIndicator = { @@ -434,10 +435,14 @@ private fun ContentScreen( viewfinder = { PreviewDisplay( + modifier = it + .fillMaxSize() + .background(Color.Black), + clippedShape = RoundedCornerShape(16.dp), previewDisplayUiState = captureUiState.previewDisplayUiState, onFlipCamera = onFlipCamera, onTapToFocus = onTapToFocus, - onScaleZoom = { onScaleZoom(it, LensToZoom.PRIMARY) }, + onScaleZoom = { scaleFactor -> onScaleZoom(scaleFactor, LensToZoom.PRIMARY) }, surfaceRequest = surfaceRequest, onRequestWindowColorMode = onRequestWindowColorMode, focusMeteringUiState = captureUiState.focusMeteringUiState @@ -453,6 +458,7 @@ private fun ContentScreen( action() } CaptureButton( + modifier = it, captureButtonUiState = captureUiState.captureButtonUiState, isQuickSettingsOpen = ( captureUiState.quickSettingsUiState as? @@ -479,7 +485,7 @@ private fun ContentScreen( }, flipCameraButton = { FlipCameraButton( - modifier = Modifier.testTag(FLIP_CAMERA_BUTTON), + modifier = it, onClick = onFlipCamera, flipLensUiState = captureUiState.flipLensUiState, // enable only when phone has front and rear camera @@ -490,14 +496,13 @@ private fun ContentScreen( ) }, zoomLevelDisplay = { - Column(modifier = Modifier, horizontalAlignment = Alignment.CenterHorizontally) { - ZoomButtonRow( - zoomControlUiState = captureUiState.zoomControlUiState, - onChangeZoom = { targetZoom -> - onAnimateZoom(targetZoom, LensToZoom.PRIMARY) - } - ) - } + ZoomButtonRow( + modifier = it, + zoomControlUiState = captureUiState.zoomControlUiState, + onChangeZoom = { targetZoom -> + onAnimateZoom(targetZoom, LensToZoom.PRIMARY) + } + ) }, elapsedTimeDisplay = { AnimatedVisibility( @@ -506,17 +511,13 @@ private fun ContentScreen( exit = fadeOut(animationSpec = tween(delayMillis = 1_500)) ) { ElapsedTimeText( - modifier = Modifier.testTag(ELAPSED_TIME_TAG), + modifier = it, elapsedTimeUiState = captureUiState.elapsedTimeUiState ) } }, quickSettingsButton = { - AnimatedVisibility( - visible = (captureUiState.videoRecordingState !is VideoRecordingState.Active), - enter = fadeIn(), - exit = fadeOut(animationSpec = tween(delayMillis = 1_500)) - ) { + if (captureUiState.videoRecordingState !is VideoRecordingState.Active) { ToggleQuickSettingsButton( modifier = it, toggleBottomSheet = onToggleQuickSettings, @@ -535,15 +536,21 @@ private fun ContentScreen( ) }, captureModeToggle = { - if (captureUiState.captureModeToggleUiState is CaptureModeToggleUiState.Available) { - CaptureModeToggleButton( - uiState = captureUiState.captureModeToggleUiState - as CaptureModeToggleUiState.Available, - - onChangeCaptureMode = onSetCaptureMode, - onToggleWhenDisabled = onDisabledCaptureMode, - modifier = it.testTag(CAPTURE_MODE_TOGGLE_BUTTON) - ) + Box( + modifier = Modifier + .defaultMinSize(minHeight = IconButtonDefaults.largeContainerSize().height), + contentAlignment = Alignment.Center + ) { + if (captureUiState.captureModeToggleUiState is CaptureModeToggleUiState.Available) { + CaptureModeToggleButton( + modifier = it, + uiState = captureUiState.captureModeToggleUiState + as CaptureModeToggleUiState.Available, + + onChangeCaptureMode = onSetCaptureMode, + onToggleWhenDisabled = onDisabledCaptureMode + ) + } } }, quickSettingsOverlay = { @@ -631,7 +638,7 @@ private fun ContentScreen( } @Composable -private fun LoadingScreen(modifier: Modifier = Modifier) { +private fun LoadingCaptureScreen(modifier: Modifier = Modifier) { Column( modifier = modifier .fillMaxSize() @@ -645,7 +652,7 @@ private fun LoadingScreen(modifier: Modifier = Modifier) { } @Composable -private fun LayoutWrapper( +private fun CaptureLayoutWrapper( modifier: Modifier = Modifier, viewfinder: @Composable (modifier: Modifier) -> Unit, captureButton: @Composable (modifier: Modifier) -> Unit, @@ -670,7 +677,7 @@ private fun LayoutWrapper( screenFlashOverlay: @Composable (modifier: Modifier) -> Unit, snackBar: @Composable (modifier: Modifier, snackbarHostState: SnackbarHostState) -> Unit ) { - PreviewLayout( + CaptureLayout( modifier = modifier, viewfinder = viewfinder, captureButton = captureButton, diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt index 72a0933d2..25565a7c1 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt @@ -19,10 +19,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -30,20 +27,23 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp // these layouts are only concerned with placement. nothing else. no state handling @Composable -fun PreviewLayout( +fun CaptureLayout( modifier: Modifier = Modifier, viewfinder: @Composable (Modifier) -> Unit, captureButton: @Composable (Modifier) -> Unit, @@ -70,13 +70,11 @@ fun PreviewLayout( indicatorRow(Modifier.statusBarsPadding()) viewfinder(Modifier) } - Box( modifier = Modifier .fillMaxSize() .padding(paddingValues) .safeDrawingPadding() - ) { debugVisibilityWrapper { VerticalMaterialControls( @@ -99,6 +97,7 @@ fun PreviewLayout( } } +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable private fun VerticalMaterialControls( modifier: Modifier = Modifier, @@ -114,161 +113,207 @@ private fun VerticalMaterialControls( Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Bottom) { Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) { + // elapsed time elapsedTimeDisplay(Modifier) - // zoom controls row + // zoom controls component zoomControls(Modifier) - // capture button row - Column { - Row( - Modifier - .fillMaxWidth() - .height(IntrinsicSize.Max), - verticalAlignment = Alignment.CenterVertically - ) { - // Row that holds flip camera, capture button, and audio - Row(Modifier.weight(1f), horizontalArrangement = Arrangement.SpaceEvenly) { - // animation fades in/out this component based on quick settings - Box( - modifier = Modifier - .weight(1f) - .height(120.dp), - contentAlignment = Alignment.Center - ) { - imageWell(Modifier) - } - } - captureButton(Modifier) - // right capturebutton item - Box( - modifier = Modifier - .weight(1f) - .height(120.dp), - contentAlignment = Alignment.Center - ) { - flipCameraButton(Modifier) - } - } - } + // capture button row + CaptureButtonRow( + modifier = Modifier.padding(24.dp), + captureButton = { captureButton(Modifier) }, + leftItem = { imageWell(Modifier) }, + rightItem = { flipCameraButton(Modifier) } + ) - Spacer( + // bottom controls row + BottomControls( modifier = Modifier - .fillMaxWidth() - // todo(kc): tune padding - .padding(bottom = 50.dp) + .padding(horizontal = 16.dp) + .padding(bottom = 24.dp), + centerItem = { captureModeToggleSwitch(Modifier) }, + leftItem = { quickSettingsToggleButton(Modifier) }, + rightItem = { } ) + } + } + bottomSheetQuickSettings(Modifier) + } +} - // bottom controls row - Row( - Modifier - .fillMaxWidth() - .defaultMinSize(minHeight = 64.dp) - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ) { - // Row that holds toggle buttons for quick settings and capture mode - // quick settings toggle switch item to the left - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.CenterStart - ) { - quickSettingsToggleButton(Modifier) - } +@Composable +private fun CaptureButtonRow( + captureButton: @Composable () -> Unit, + modifier: Modifier = Modifier, + leftItem: @Composable () -> Unit = {}, + rightItem: @Composable () -> Unit = {} +) { + Row( + modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + // Left controls (imageWell) + Box( + modifier = Modifier + .weight(1f), + contentAlignment = Alignment.Center + ) { + leftItem() + } - // capture mode toggle switch center - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.Center - ) { - captureModeToggleSwitch(Modifier) - } + // Capture Button at Center + captureButton() - // right toggle switch item to the right - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.CenterEnd - ) {} - } - } + // Right controls (flipCameraButton) + Box( + modifier = Modifier + .weight(1f), + contentAlignment = Alignment.Center + ) { + rightItem() + } + } +} + +@Composable +private fun BottomControls( + centerItem: @Composable () -> Unit, + modifier: Modifier = Modifier, + leftItem: @Composable () -> Unit = {}, + rightItem: @Composable () -> Unit = {} +) { + Row( + modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + // Row that holds toggle buttons for quick settings and capture mode + // quick settings toggle switch item to the left + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterStart + ) { + leftItem() + } + + // capture mode toggle switch center + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.Center + ) { + centerItem() + } + + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.CenterEnd + ) { + rightItem() } - bottomSheetQuickSettings(Modifier) } } @Preview @Composable private fun CaptureLayoutPreview() { - PreviewLayout( + CaptureLayout( modifier = Modifier.background(Color.Black), viewfinder = { modifier -> Box( modifier = modifier .fillMaxWidth() .height(600.dp) - .background(Color.DarkGray) - ) + .background(Color.DarkGray), + contentAlignment = Alignment.Center + ) { + Text(text = "viewfinder", textAlign = TextAlign.Center, color = Color.White) + } }, captureButton = { modifier -> Box( modifier = modifier .size(80.dp) - .background(Color.White) - ) + .background(Color.White), + contentAlignment = Alignment.Center + ) { + Text(text = "capture button", textAlign = TextAlign.Center) + } }, flipCameraButton = { modifier -> Box( modifier = modifier .size(48.dp) - .background(Color.Cyan) - ) + .background(Color.Cyan), + contentAlignment = Alignment.Center + ) { + Text(text = "flip camera ", textAlign = TextAlign.Center) + } }, imageWell = { modifier -> Box( modifier = modifier .size(48.dp) - .background(Color.Cyan) - ) + .background(Color.Green), + contentAlignment = Alignment.Center + ) { + Text(text = "image well", textAlign = TextAlign.Center) + } }, zoomLevelDisplay = { modifier -> Box( modifier = modifier .height(48.dp) - .fillMaxWidth() - .background(Color.Magenta) - ) + .fillMaxWidth(.5f) + .background(Color.Magenta), + contentAlignment = Alignment.Center + ) { + Text(text = "zoom controls", textAlign = TextAlign.Center) + } }, elapsedTimeDisplay = { modifier -> Box( modifier = modifier .height(24.dp) - .fillMaxWidth(0.5f) - .background(Color.Red) - ) + .fillMaxWidth(0.25f) + .background(Color.Red), + contentAlignment = Alignment.Center + ) { + Text(text = "elapsed time", textAlign = TextAlign.Center) + } }, quickSettingsButton = { modifier -> Box( modifier = modifier .size(48.dp) - .background(Color.Yellow) - ) + .background(Color.Yellow), + contentAlignment = Alignment.Center + ) { + Text(text = "quick setting toggle", textAlign = TextAlign.Center) + } }, indicatorRow = { modifier -> Box( modifier = modifier .height(48.dp) .fillMaxWidth() - .background(Color.Green) - ) + .background(Color.Green), + contentAlignment = Alignment.Center + ) { + Text(text = "indicators row") + } }, captureModeToggle = { modifier -> Box( modifier = modifier .height(48.dp) .fillMaxWidth(0.5f) - .background(Color.Blue) - ) + .background(Color.Blue), + contentAlignment = Alignment.Center + ) { + Text(text = "capture toggle", textAlign = TextAlign.Center, color = Color.Yellow) + } }, quickSettingsOverlay = { // No-op for preview diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt index 7a06a0826..0b08ae785 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt @@ -41,7 +41,6 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn import androidx.compose.animation.scaleOut -import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.rememberTransformableState @@ -54,7 +53,6 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CameraAlt import androidx.compose.material.icons.filled.FlipCameraAndroid @@ -94,6 +92,7 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Matrix +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext @@ -138,7 +137,7 @@ private const val FOCUS_INDICATOR_RESULT_DELAY = 100L fun ElapsedTimeText(modifier: Modifier = Modifier, elapsedTimeUiState: ElapsedTimeUiState) { if (elapsedTimeUiState is ElapsedTimeUiState.Enabled) { Text( - modifier = modifier, + modifier = modifier.testTag(ELAPSED_TIME_TAG), text = elapsedTimeUiState.elapsedTimeNanos.nanoseconds .toComponents { minutes, seconds, _ -> "%02d:%02d".format(minutes, seconds) }, textAlign = TextAlign.Center @@ -407,7 +406,8 @@ fun PreviewDisplay( onRequestWindowColorMode: (Int) -> Unit, surfaceRequest: SurfaceRequest?, focusMeteringUiState: FocusMeteringUiState, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + clippedShape: Shape? = null ) { if (previewDisplayUiState.aspectRatioUiState !is AspectRatioUiState.Available) { return @@ -420,10 +420,7 @@ fun PreviewDisplay( surfaceRequest?.let { BoxWithConstraints( - modifier - .testTag(PREVIEW_DISPLAY) - .fillMaxSize() - .background(Color.Black), + modifier = modifier.testTag(PREVIEW_DISPLAY), contentAlignment = Alignment.TopCenter ) { val aspectRatio = ( @@ -460,7 +457,11 @@ fun PreviewDisplay( .height(height) .transformable(state = transformableState) .alpha(imageAlpha) - .clip(RoundedCornerShape(16.dp)) + .apply { + clippedShape?.let { + clip(clippedShape) + } + } ) { val implementationMode = when { Build.VERSION.SDK_INT > 24 -> ImplementationMode.EXTERNAL @@ -634,7 +635,9 @@ fun VideoQualityIcon(videoQuality: VideoQuality, modifier: Modifier = Modifier) CompositionLocalProvider(LocalContentColor provides Color.White) { if (videoQuality != VideoQuality.UNSPECIFIED) { Icon( - modifier = modifier.size(IconButtonDefaults.smallIconSize), + modifier = modifier + .testTag(VIDEO_QUALITY_TAG) + .size(IconButtonDefaults.smallIconSize), painter = when (videoQuality) { VideoQuality.SD -> @@ -706,7 +709,7 @@ fun FlipCameraButton( } } IconButton( - modifier = modifier, + modifier = modifier.testTag(FLIP_CAMERA_BUTTON), onClick = onClick, enabled = enabledCondition ) { diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt index 98e2e856c..742c64cae 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt @@ -19,7 +19,7 @@ import android.net.Uri import androidx.compose.animation.AnimatedContent import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.spring -import androidx.compose.animation.expandHorizontally +import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn @@ -54,25 +54,40 @@ fun ImageWell( imageWellUiState: ImageWellUiState.LastCapture, onClick: () -> Unit, modifier: Modifier = Modifier, - shape: Shape = RoundedCornerShape(16.dp), + shape: Shape? = RoundedCornerShape(16.dp), enabled: Boolean = true ) { val lastCapture = imageWellUiState.mediaDescriptor + var currentModifier = modifier + .testTag(IMAGE_WELL_TAG) + .size(IconButtonDefaults.mediumContainerSize()) + .clickable(onClick = onClick, enabled = enabled) + + shape?.let { s -> + currentModifier = currentModifier + .border(2.dp, Color.White, s) + .clip(s) + } Box( - modifier = modifier + modifier = currentModifier .testTag(IMAGE_WELL_TAG) .size(IconButtonDefaults.mediumContainerSize()) - .border(2.dp, Color.White, shape) - .clip(shape) .clickable(onClick = onClick, enabled = enabled) + .apply { + shape?.let { + println("shape is not null") + border(2.dp, Color.White, it) + clip(it) + } ?: println("shape is null") + } ) { AnimatedContent( targetState = lastCapture, label = "ImageWellAnimation", transitionSpec = { ( - fadeIn() + expandHorizontally() + + fadeIn() + expandVertically() + scaleIn(animationSpec = spring(0.8f)) ).togetherWith(fadeOut()) } diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt index 51387b5ba..1921713e2 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt @@ -471,7 +471,8 @@ fun QuickSetConcurrentCamera( fun ToggleQuickSettingsButton( toggleBottomSheet: () -> Unit, isOpen: Boolean, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + enabled: Boolean = true ) { val buttonSize = IconButtonDefaults.mediumContainerSize( IconButtonDefaults.IconButtonWidthOption.Narrow @@ -483,13 +484,13 @@ fun ToggleQuickSettingsButton( .size(buttonSize) .testTag(QUICK_SETTINGS_DROP_DOWN) .semantics { - testTag = QUICK_SETTINGS_DROP_DOWN contentDescription = if (isOpen) { openDescription } else { closedDescription } }, + enabled = enabled, onClick = toggleBottomSheet, colors = IconButtonDefaults.iconButtonColors( // Set the background color of the button @@ -895,8 +896,7 @@ private fun QuickSettingToggleButtonPreview() { ) { Row( modifier = Modifier - .width(300.dp) - .height(180.dp), + .width(200.dp), horizontalArrangement = Arrangement.SpaceBetween ) { // Instance 1: Unchecked state