summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimberly Crevecoeur <kcrevecoeur@google.com>2024-01-18 18:19:54 -0800
committerGitHub <noreply@github.com>2024-01-19 02:19:54 +0000
commit42fad7995f353de3587ffe233b423fc54122a492 (patch)
tree7778ce391abcfbc7c943af03f5dc45da8d243b73
parentaf8241c0573e78458b464a6cfba41ed49236da9c (diff)
downloadjetpack-camera-app-42fad7995f353de3587ffe233b423fc54122a492.tar.gz
Preview screen layout refactor (#96)
* small preview refactor to better organize components * convert preview overlay layer to a relative/grid layout style
-rw-r--r--feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt279
-rw-r--r--feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/ui/PreviewScreenComponents.kt27
-rw-r--r--feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt8
-rw-r--r--feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/ui/QuickSettingsComponents.kt9
4 files changed, 183 insertions, 140 deletions
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 0f8fdcb..5aeb5c0 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
@@ -22,7 +22,6 @@ import android.util.Log
import androidx.camera.core.Preview.SurfaceProvider
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
@@ -66,8 +65,9 @@ import com.google.jetpackcamera.feature.preview.ui.SettingsNavButton
import com.google.jetpackcamera.feature.preview.ui.ShowTestableToast
import com.google.jetpackcamera.feature.preview.ui.TestingButton
import com.google.jetpackcamera.feature.preview.ui.ZoomScaleText
-import com.google.jetpackcamera.feature.quicksettings.QuickSettingsScreen
+import com.google.jetpackcamera.feature.quicksettings.QuickSettingsScreenOverlay
import com.google.jetpackcamera.feature.quicksettings.ui.QuickSettingsIndicators
+import com.google.jetpackcamera.feature.quicksettings.ui.ToggleQuickSettingsButton
import com.google.jetpackcamera.settings.model.CaptureMode
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.awaitCancellation
@@ -140,8 +140,21 @@ fun PreviewScreen(
aspectRatio = previewUiState.currentCameraSettings.aspectRatio,
deferredSurfaceProvider = deferredSurfaceProvider
)
- // overlay
- Box(
+
+ QuickSettingsScreenOverlay(
+ modifier = Modifier,
+ isOpen = previewUiState.quickSettingsIsOpen,
+ toggleIsOpen = { viewModel.toggleQuickSettings() },
+ currentCameraSettings = previewUiState.currentCameraSettings,
+ onLensFaceClick = viewModel::flipCamera,
+ onFlashModeClick = viewModel::setFlash,
+ onAspectRatioClick = {
+ viewModel.setAspectRatio(it)
+ }
+ // onTimerClick = {}/*TODO*/
+ )
+ // relative-grid style overlay on top of preview display
+ Column(
modifier = Modifier
.semantics {
testTagsAsResourceId = true
@@ -152,138 +165,170 @@ fun PreviewScreen(
when (previewUiState.videoRecordingState) {
VideoRecordingState.ACTIVE -> {}
VideoRecordingState.INACTIVE -> {
- QuickSettingsScreen(
- modifier = Modifier
- .align(Alignment.TopCenter),
- isOpen = previewUiState.quickSettingsIsOpen,
- toggleIsOpen = { viewModel.toggleQuickSettings() },
- currentCameraSettings = previewUiState.currentCameraSettings,
- onLensFaceClick = viewModel::flipCamera,
- onFlashModeClick = viewModel::setFlash,
- onAspectRatioClick = {
- viewModel.setAspectRatio(it)
- }
- // onTimerClick = {}/*TODO*/
- )
-
+ // 3-segmented row to keep quick settings button centered
Row(
modifier = Modifier
- .align(Alignment.TopStart),
- horizontalArrangement = Arrangement.Start,
- verticalAlignment = Alignment.CenterVertically
+ .fillMaxWidth()
+ .height(IntrinsicSize.Min)
) {
- SettingsNavButton(
+ // row to left of quick settings button
+ Row(
modifier = Modifier
- .padding(12.dp),
- onNavigateToSettings = onNavigateToSettings
- )
-
- QuickSettingsIndicators(
- currentCameraSettings = previewUiState.currentCameraSettings,
- onFlashModeClick = viewModel::setFlash
- )
- }
-
- TestingButton(
- modifier = Modifier
- .testTag("ToggleCaptureMode")
- .align(Alignment.TopEnd)
- .padding(12.dp),
- onClick = { viewModel.toggleCaptureMode() },
- text = stringResource(
- when (previewUiState.currentCameraSettings.captureMode) {
- CaptureMode.SINGLE_STREAM -> R.string.capture_mode_single_stream
- CaptureMode.MULTI_STREAM -> R.string.capture_mode_multi_stream
- }
- )
- )
- }
- }
-
- Column(
- horizontalAlignment = Alignment.CenterHorizontally,
- modifier = Modifier.align(Alignment.BottomCenter)
- ) {
- if (zoomScaleShow) {
- ZoomScaleText(zoomScale = zoomScale)
- }
- Row(
- modifier =
- Modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Min)
- ) {
- when (previewUiState.videoRecordingState) {
- VideoRecordingState.ACTIVE -> {
- Spacer(
+ .weight(1f),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // button to open default settings page
+ SettingsNavButton(
modifier = Modifier
- .fillMaxHeight()
- .weight(1f)
+ .padding(12.dp),
+ onNavigateToSettings = onNavigateToSettings
)
+ if (!previewUiState.quickSettingsIsOpen) {
+ QuickSettingsIndicators(
+ currentCameraSettings = previewUiState.currentCameraSettings,
+ onFlashModeClick = viewModel::setFlash
+ )
+ }
}
+ // quick settings button
+ ToggleQuickSettingsButton(
+ toggleDropDown = { viewModel.toggleQuickSettings() },
+ isOpen = previewUiState.quickSettingsIsOpen
+ )
- VideoRecordingState.INACTIVE -> {
- FlipCameraButton(
+ // Row to right of quick settings
+ Row(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxHeight(),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ TestingButton(
modifier = Modifier
- .weight(1f)
- .fillMaxHeight(),
- onClick = { viewModel.flipCamera() },
- // enable only when phone has front and rear camera
- enabledCondition =
- previewUiState.currentCameraSettings.isBackCameraAvailable &&
- previewUiState.currentCameraSettings.isFrontCameraAvailable
+ .testTag("ToggleCaptureMode"),
+ onClick = { viewModel.toggleCaptureMode() },
+ text = stringResource(
+ when (previewUiState.currentCameraSettings.captureMode) {
+ CaptureMode.SINGLE_STREAM ->
+ R.string.capture_mode_single_stream
+
+ CaptureMode.MULTI_STREAM ->
+ R.string.capture_mode_multi_stream
+ }
+ )
)
}
}
- val multipleEventsCutter = remember { MultipleEventsCutter() }
- val context = LocalContext.current
- /*todo: close quick settings on start record/image capture*/
- CaptureButton(
- modifier = Modifier
- .testTag(CAPTURE_BUTTON),
- onClick = {
- multipleEventsCutter.processEvent {
- when (previewMode) {
- is PreviewMode.StandardMode -> {
- viewModel.captureImage()
- }
+ }
+ }
- is PreviewMode.ExternalImageCaptureMode -> {
- viewModel.captureImage(
- context.contentResolver,
- previewMode.imageCaptureUri,
- previewMode.onImageCapture
- )
- }
- }
+ // this component places a gap in the center of the column that will push out the top
+ // and bottom edges. This will also allow the addition of vertical button bars on the
+ // sides of the screen
+ Row(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxWidth()
+ ) {}
+
+ if (zoomScaleShow) {
+ ZoomScaleText(zoomScale = zoomScale)
+ }
+
+ // 3-segmented row to keep capture button centered
+ Row(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .height(IntrinsicSize.Min)
+ ) {
+ when (previewUiState.videoRecordingState) {
+ // hide first segment while recording in progress
+ VideoRecordingState.ACTIVE -> {
+ Spacer(
+ modifier = Modifier
+ .fillMaxHeight()
+ .weight(1f)
+ )
+ }
+ // show first segment when not recording
+ VideoRecordingState.INACTIVE -> {
+ Row(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxHeight(),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ if (!previewUiState.quickSettingsIsOpen) {
+ FlipCameraButton(
+ onClick = { viewModel.flipCamera() },
+ // enable only when phone has front and rear camera
+ enabledCondition =
+ previewUiState.currentCameraSettings.isBackCameraAvailable &&
+ previewUiState.currentCameraSettings
+ .isFrontCameraAvailable
+ )
}
- },
- onLongPress = { viewModel.startVideoRecording() },
- onRelease = { viewModel.stopVideoRecording() },
- videoRecordingState = previewUiState.videoRecordingState
- )
- /* spacer is a placeholder to maintain the proportionate location of this
- row of UI elements. if you want to add another element, replace it with ONE
- element. If you want to add multiple components, use a container
- (Box, Row, Column, etc.)
- */
- Spacer(
- modifier = Modifier
- .fillMaxHeight()
- .weight(1f)
- )
+ }
+ }
}
- }
- // displays toast when there is a message to show
- if (previewUiState.toastMessageToShow != null) {
- ShowTestableToast(
+ val multipleEventsCutter = remember { MultipleEventsCutter() }
+ val context = LocalContext.current
+ CaptureButton(
modifier = Modifier
- .testTag(previewUiState.toastMessageToShow!!.testTag),
- toastMessage = previewUiState.toastMessageToShow!!,
- onToastShown = viewModel::onToastShown
+ .testTag(CAPTURE_BUTTON),
+ onClick = {
+ multipleEventsCutter.processEvent {
+ when (previewMode) {
+ is PreviewMode.StandardMode -> {
+ viewModel.captureImage()
+ }
+
+ is PreviewMode.ExternalImageCaptureMode -> {
+ viewModel.captureImage(
+ context.contentResolver,
+ previewMode.imageCaptureUri,
+ previewMode.onImageCapture
+ )
+ }
+ }
+ }
+ if (previewUiState.quickSettingsIsOpen) {
+ viewModel.toggleQuickSettings()
+ }
+ },
+ onLongPress = {
+ viewModel.startVideoRecording()
+ if (previewUiState.quickSettingsIsOpen) {
+ viewModel.toggleQuickSettings()
+ }
+ },
+ onRelease = { viewModel.stopVideoRecording() },
+ videoRecordingState = previewUiState.videoRecordingState
)
+ // You can replace this row so long as the weight of the component is 1f to
+ // ensure the capture button remains centered.
+ Row(
+ modifier = Modifier
+ .fillMaxHeight()
+ .weight(1f)
+ ) {
+ /*TODO("Place other components here") */
+ }
}
}
+ // displays toast when there is a message to show
+ if (previewUiState.toastMessageToShow != null) {
+ ShowTestableToast(
+ modifier = Modifier
+ .testTag(previewUiState.toastMessageToShow!!.testTag),
+ toastMessage = previewUiState.toastMessageToShow!!,
+ onToastShown = viewModel::onToastShown
+ )
+ }
// Screen flash overlay that stays on top of everything but invisible normally. This should
// not be enabled based on whether screen flash is enabled because a previous image capture
diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/ui/PreviewScreenComponents.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/ui/PreviewScreenComponents.kt
index 6d16f1d..5c7b5ab 100644
--- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/ui/PreviewScreenComponents.kt
+++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/ui/PreviewScreenComponents.kt
@@ -202,21 +202,18 @@ fun FlipCameraButton(
enabledCondition: Boolean,
onClick: () -> Unit
) {
- Box(modifier = modifier) {
- IconButton(
- modifier = Modifier
- .align(Alignment.Center)
- .size(40.dp),
- onClick = onClick,
- enabled = enabledCondition
- ) {
- Icon(
- imageVector = Icons.Filled.Refresh,
- tint = Color.White,
- contentDescription = stringResource(id = R.string.flip_camera_content_description),
- modifier = Modifier.size(72.dp)
- )
- }
+ IconButton(
+ modifier = modifier
+ .size(40.dp),
+ onClick = onClick,
+ enabled = enabledCondition
+ ) {
+ Icon(
+ imageVector = Icons.Filled.Refresh,
+ tint = Color.White,
+ contentDescription = stringResource(id = R.string.flip_camera_content_description),
+ modifier = Modifier.size(72.dp)
+ )
}
}
diff --git a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
index 6b0ba2f..e6b2ff9 100644
--- a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
+++ b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
@@ -38,7 +38,6 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
-import com.google.jetpackcamera.feature.quicksettings.ui.DropDownIcon
import com.google.jetpackcamera.feature.quicksettings.ui.ExpandedQuickSetRatio
import com.google.jetpackcamera.feature.quicksettings.ui.QuickFlipCamera
import com.google.jetpackcamera.feature.quicksettings.ui.QuickSetFlash
@@ -54,7 +53,7 @@ import com.google.jetpackcamera.settings.model.FlashMode
*/
@OptIn(ExperimentalComposeUiApi::class)
@Composable
-fun QuickSettingsScreen(
+fun QuickSettingsScreenOverlay(
modifier: Modifier = Modifier,
currentCameraSettings: CameraAppSettings,
isOpen: Boolean = false,
@@ -115,11 +114,6 @@ fun QuickSettingsScreen(
} else {
shouldShowQuickSetting = IsExpandedQuickSetting.NONE
}
- DropDownIcon(
- modifier = modifier,
- toggleDropDown = toggleIsOpen,
- isOpen = isOpen
- )
}
// enum representing which individual quick setting is currently expanded
diff --git a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/ui/QuickSettingsComponents.kt b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/ui/QuickSettingsComponents.kt
index d3bb28c..3242f35 100644
--- a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/ui/QuickSettingsComponents.kt
+++ b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/ui/QuickSettingsComponents.kt
@@ -164,8 +164,15 @@ fun QuickFlipCamera(
)
}
+/**
+ * Button to toggle quick settings
+ */
@Composable
-fun DropDownIcon(modifier: Modifier = Modifier, toggleDropDown: () -> Unit, isOpen: Boolean) {
+fun ToggleQuickSettingsButton(
+ modifier: Modifier = Modifier,
+ toggleDropDown: () -> Unit,
+ isOpen: Boolean
+) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.Center,