From e29ef701ee6d96b226996899efbb3b4aa8f3ac40 Mon Sep 17 00:00:00 2001 From: manpreet Date: Sun, 22 Dec 2024 17:10:32 -0700 Subject: [PATCH 1/4] (MVP): Add landscape support for the PIN layout. --- .../mauth/ui/component/pinboard/PinBoard.kt | 168 +++++++++++++----- .../ui/component/pinboard/PinScaffold.kt | 122 +++++++++---- 2 files changed, 219 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt index 4948a34..60dc283 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt @@ -3,6 +3,7 @@ package com.xinto.mauth.ui.component.pinboard import android.content.res.Configuration import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowColumn import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio @@ -17,6 +18,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -29,54 +31,140 @@ fun PinBoard( modifier: Modifier = Modifier, state: PinBoardState = rememberPinBoardState() ) { - FlowRow( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), - maxItemsInEachRow = 3 - ) { - state.buttons.forEach { button -> - when (button) { - is PinBoardState.PinBoardButton.Number -> { - PinButton( - modifier = Modifier.weight(1f), - onClick = { state.onNumberClick(button.number) } - ) { - Text(button.toString()) + val orientation = LocalConfiguration.current.orientation + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + + FlowColumn( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), + maxItemsInEachColumn = 4 + ) { + val rowCount = 4 + val rowWidth = 3 + val columnCount = 3 + val columnButtons = buildList { + for (columnIndex in 0.. { - PrimaryPinButton( - modifier = Modifier.weight(1f), - onClick = when (button) { - is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick - is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick - is PinBoardState.PinBoardButton.Enter -> state.onEnterClick - else -> throw NoSuchElementException() - }, - onLongClick = + } + columnButtons.forEach { button -> + when (button) { + is PinBoardState.PinBoardButton.Number -> { + PinButton( + modifier = Modifier.weight(1f), + onClick = { state.onNumberClick(button.number) } + ) { + Text(button.toString()) + } + } + + is PinBoardState.PinBoardButton.Backspace, + is PinBoardState.PinBoardButton.Fingerprint, + is PinBoardState.PinBoardButton.Enter -> { + PrimaryPinButton( + modifier = Modifier.weight(1f), + onClick = when (button) { + is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick + is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick + is PinBoardState.PinBoardButton.Enter -> state.onEnterClick + else -> throw NoSuchElementException() + }, + onLongClick = if (button is PinBoardState.PinBoardButton.Backspace) state.onBackspaceLongClick else null - ) { - Icon( - modifier = Modifier.fillMaxSize(0.4f).aspectRatio(1f), - painter = painterResource( - id = when (button) { - is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace - is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint - is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab - else -> throw NoSuchElementException() - } - ), - contentDescription = null + ) { + Icon( + modifier = Modifier + .fillMaxSize(0.4f) + .aspectRatio(1f), + painter = painterResource( + id = when (button) { + is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace + is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint + is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab + else -> throw NoSuchElementException() + } + ), + contentDescription = null + ) + } + } + + is PinBoardState.PinBoardButton.Empty -> { + Spacer( + Modifier + .aspectRatio(1f) + .weight(1f) + .size(PinButtonDefaults.PinButtonMinSize) ) } } - is PinBoardState.PinBoardButton.Empty -> { - Spacer(Modifier.aspectRatio(1f).weight(1f).size(PinButtonDefaults.PinButtonMinSize)) + } + } + } else { + + FlowRow( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), + horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), + maxItemsInEachRow = 3 + ) { + state.buttons.forEach { button -> + when (button) { + is PinBoardState.PinBoardButton.Number -> { + PinButton( + modifier = Modifier.weight(1f), + onClick = { state.onNumberClick(button.number) } + ) { + Text(button.toString()) + } + } + + is PinBoardState.PinBoardButton.Backspace, + is PinBoardState.PinBoardButton.Fingerprint, + is PinBoardState.PinBoardButton.Enter -> { + PrimaryPinButton( + modifier = Modifier.weight(1f), + onClick = when (button) { + is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick + is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick + is PinBoardState.PinBoardButton.Enter -> state.onEnterClick + else -> throw NoSuchElementException() + }, + onLongClick = + if (button is PinBoardState.PinBoardButton.Backspace) + state.onBackspaceLongClick + else null + ) { + Icon( + modifier = Modifier + .fillMaxSize(0.4f) + .aspectRatio(1f), + painter = painterResource( + id = when (button) { + is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace + is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint + is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab + else -> throw NoSuchElementException() + } + ), + contentDescription = null + ) + } + } + + is PinBoardState.PinBoardButton.Empty -> { + Spacer( + Modifier + .aspectRatio(1f) + .weight(1f) + .size(PinButtonDefaults.PinButtonMinSize) + ) + } } } } diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt index 5eac848..187b307 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt @@ -4,10 +4,12 @@ import android.content.res.Configuration 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.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.FabPosition import androidx.compose.material3.LocalTextStyle @@ -21,6 +23,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -53,44 +56,101 @@ fun PinScaffold( contentColor = contentColor, contentWindowInsets = contentWindowInsets, ) { - Column( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .padding(it) - .padding(40.dp) - .padding(bottom = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Bottom), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (description != null) { - Spacer(modifier = Modifier.weight(1f)) + val orientation = LocalConfiguration.current.orientation + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + Row( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(it) + .padding(20.dp) + .padding(bottom = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center + modifier = Modifier + .weight(0.6f) + .fillMaxHeight() ) { - CompositionLocalProvider( - LocalTextStyle provides MaterialTheme.typography.headlineMedium.copy( - textAlign = TextAlign.Center - ) + Column( + modifier = Modifier.fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally ) { - description() + if (description != null) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.headlineMedium.copy( + textAlign = TextAlign.Center + ) + ) { + description() + } + } + Spacer(modifier = Modifier.height(32.dp)) + } + PinDisplay( + modifier = Modifier + .fillMaxWidth(0.5f), + length = codeLength, + error = error, + ) } } - Spacer(modifier = Modifier.weight(1f)) + Box(modifier = Modifier.weight(0.4f)) { + PinBoard( + modifier = Modifier + .padding(horizontal = 32.dp) + .padding(bottom = 16.dp), + state = state + ) + } } - PinDisplay( - modifier = Modifier - .fillMaxWidth(), - length = codeLength, - error = error, - ) - PinBoard( + } else { + + Column( modifier = Modifier - .padding(horizontal = 8.dp) - .padding(top = 32.dp), - state = state - ) + .fillMaxWidth() + .fillMaxHeight() + .padding(it) + .padding(40.dp) + .padding(bottom = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Bottom), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (description != null) { + Spacer(modifier = Modifier.weight(1f)) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.headlineMedium.copy( + textAlign = TextAlign.Center + ) + ) { + description() + } + } + Spacer(modifier = Modifier.weight(1f)) + } + PinDisplay( + modifier = Modifier + .fillMaxWidth(), + length = codeLength, + error = error, + ) + PinBoard( + modifier = Modifier + .padding(horizontal = 8.dp) + .padding(top = 32.dp), + state = state + ) + } } } } From b3117d0ce7b1198f80e88c4734ec33154c0457ca Mon Sep 17 00:00:00 2001 From: manpreet Date: Tue, 24 Dec 2024 12:09:47 -0700 Subject: [PATCH 2/4] Manually calculate the width required to fit 3 pin buttons. In landscape mode, height is the limiting constraint. So, this calculation tries to fit exactly 3 buttons in a row using their `PinButtonDefaults.PinButtonMinSize`. --- .../mauth/ui/component/pinboard/PinBoard.kt | 170 +++++------------- .../ui/component/pinboard/PinScaffold.kt | 23 ++- 2 files changed, 60 insertions(+), 133 deletions(-) diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt index 60dc283..825239c 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt @@ -3,7 +3,6 @@ package com.xinto.mauth.ui.component.pinboard import android.content.res.Configuration import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowColumn import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio @@ -18,9 +17,9 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.xinto.mauth.R import com.xinto.mauth.ui.theme.MauthTheme @@ -29,142 +28,57 @@ import com.xinto.mauth.ui.theme.MauthTheme @Composable fun PinBoard( modifier: Modifier = Modifier, + horizontalButtonSpace: Dp = 16.dp, state: PinBoardState = rememberPinBoardState() ) { - val orientation = LocalConfiguration.current.orientation - if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - - FlowColumn( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), - maxItemsInEachColumn = 4 - ) { - val rowCount = 4 - val rowWidth = 3 - val columnCount = 3 - val columnButtons = buildList { - for (columnIndex in 0.. + when (button) { + is PinBoardState.PinBoardButton.Number -> { + PinButton( + modifier = Modifier.weight(1f), + onClick = { state.onNumberClick(button.number) } + ) { + Text(button.toString()) } } - } - columnButtons.forEach { button -> - when (button) { - is PinBoardState.PinBoardButton.Number -> { - PinButton( - modifier = Modifier.weight(1f), - onClick = { state.onNumberClick(button.number) } - ) { - Text(button.toString()) - } - } - - is PinBoardState.PinBoardButton.Backspace, - is PinBoardState.PinBoardButton.Fingerprint, - is PinBoardState.PinBoardButton.Enter -> { - PrimaryPinButton( - modifier = Modifier.weight(1f), - onClick = when (button) { - is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick - is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick - is PinBoardState.PinBoardButton.Enter -> state.onEnterClick - else -> throw NoSuchElementException() - }, - onLongClick = + is PinBoardState.PinBoardButton.Backspace, + is PinBoardState.PinBoardButton.Fingerprint, + is PinBoardState.PinBoardButton.Enter -> { + PrimaryPinButton( + modifier = Modifier.weight(1f), + onClick = when (button) { + is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick + is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick + is PinBoardState.PinBoardButton.Enter -> state.onEnterClick + else -> throw NoSuchElementException() + }, + onLongClick = if (button is PinBoardState.PinBoardButton.Backspace) state.onBackspaceLongClick else null - ) { - Icon( - modifier = Modifier - .fillMaxSize(0.4f) - .aspectRatio(1f), - painter = painterResource( - id = when (button) { - is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace - is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint - is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab - else -> throw NoSuchElementException() - } - ), - contentDescription = null - ) - } - } - - is PinBoardState.PinBoardButton.Empty -> { - Spacer( - Modifier - .aspectRatio(1f) - .weight(1f) - .size(PinButtonDefaults.PinButtonMinSize) + ) { + Icon( + modifier = Modifier.fillMaxSize(0.4f).aspectRatio(1f), + painter = painterResource( + id = when (button) { + is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace + is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint + is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab + else -> throw NoSuchElementException() + } + ), + contentDescription = null ) } } - } - } - } else { - - FlowRow( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically), - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), - maxItemsInEachRow = 3 - ) { - state.buttons.forEach { button -> - when (button) { - is PinBoardState.PinBoardButton.Number -> { - PinButton( - modifier = Modifier.weight(1f), - onClick = { state.onNumberClick(button.number) } - ) { - Text(button.toString()) - } - } - - is PinBoardState.PinBoardButton.Backspace, - is PinBoardState.PinBoardButton.Fingerprint, - is PinBoardState.PinBoardButton.Enter -> { - PrimaryPinButton( - modifier = Modifier.weight(1f), - onClick = when (button) { - is PinBoardState.PinBoardButton.Backspace -> state.onBackspaceClick - is PinBoardState.PinBoardButton.Fingerprint -> state.onFingerprintClick - is PinBoardState.PinBoardButton.Enter -> state.onEnterClick - else -> throw NoSuchElementException() - }, - onLongClick = - if (button is PinBoardState.PinBoardButton.Backspace) - state.onBackspaceLongClick - else null - ) { - Icon( - modifier = Modifier - .fillMaxSize(0.4f) - .aspectRatio(1f), - painter = painterResource( - id = when (button) { - is PinBoardState.PinBoardButton.Backspace -> R.drawable.ic_backspace - is PinBoardState.PinBoardButton.Fingerprint -> R.drawable.ic_fingerprint - is PinBoardState.PinBoardButton.Enter -> R.drawable.ic_tab - else -> throw NoSuchElementException() - } - ), - contentDescription = null - ) - } - } - - is PinBoardState.PinBoardButton.Empty -> { - Spacer( - Modifier - .aspectRatio(1f) - .weight(1f) - .size(PinButtonDefaults.PinButtonMinSize) - ) - } + is PinBoardState.PinBoardButton.Empty -> { + Spacer(Modifier.aspectRatio(1f).weight(1f).size(PinButtonDefaults.PinButtonMinSize)) } } } diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt index 187b307..6d61bf4 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.sizeIn import androidx.compose.material3.FabPosition import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme @@ -20,6 +21,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -63,14 +65,14 @@ fun PinScaffold( .fillMaxWidth() .fillMaxHeight() .padding(it) - .padding(20.dp) + .padding(horizontal = 20.dp) .padding(bottom = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, + horizontalArrangement = Arrangement.SpaceAround, verticalAlignment = Alignment.CenterVertically ) { Box( modifier = Modifier - .weight(0.6f) + .fillMaxWidth(0.5f) .fillMaxHeight() ) { Column( @@ -101,11 +103,22 @@ fun PinScaffold( ) } } - Box(modifier = Modifier.weight(0.4f)) { + val pinBoardHorizontalPadding = 32.dp + val horizontalButtonSpace = 16.dp + val totalPadding = (pinBoardHorizontalPadding * 2) + (horizontalButtonSpace * 2) + val maxBoxWidth = remember(PinButtonDefaults.PinButtonMinSize) { + val buttonsInRow = 3 + (PinButtonDefaults.PinButtonMinSize * buttonsInRow) + totalPadding + } + Box( + modifier = Modifier.sizeIn(maxWidth = maxBoxWidth), + contentAlignment = Alignment.Center + ) { PinBoard( modifier = Modifier - .padding(horizontal = 32.dp) + .padding(horizontal = pinBoardHorizontalPadding) .padding(bottom = 16.dp), + horizontalButtonSpace = horizontalButtonSpace, state = state ) } From f73976baf66aa3d5d17c98b62bfb1eabbcfcb4a6 Mon Sep 17 00:00:00 2001 From: manpreet Date: Fri, 3 Jan 2025 14:53:28 -0700 Subject: [PATCH 3/4] Add small button size and update PinSetupScreen and PinRemoveScreen to use the small button size. --- .../mauth/ui/component/pinboard/PinBoard.kt | 13 ++-- .../mauth/ui/component/pinboard/PinButton.kt | 19 ++++-- .../ui/component/pinboard/PinScaffold.kt | 24 ++++--- .../ui/screen/pinremove/PinRemoveScreen.kt | 44 ++++++++---- .../ui/screen/pinsetup/PinSetupScreen.kt | 68 ++++++++++++------- 5 files changed, 109 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt index 825239c..46a6be3 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinBoard.kt @@ -29,6 +29,7 @@ import com.xinto.mauth.ui.theme.MauthTheme fun PinBoard( modifier: Modifier = Modifier, horizontalButtonSpace: Dp = 16.dp, + minButtonSize: Dp = PinButtonDefaults.PinButtonNormalMinSize, state: PinBoardState = rememberPinBoardState() ) { FlowRow( @@ -42,7 +43,8 @@ fun PinBoard( is PinBoardState.PinBoardButton.Number -> { PinButton( modifier = Modifier.weight(1f), - onClick = { state.onNumberClick(button.number) } + onClick = { state.onNumberClick(button.number) }, + minButtonSize = minButtonSize ) { Text(button.toString()) } @@ -59,9 +61,10 @@ fun PinBoard( else -> throw NoSuchElementException() }, onLongClick = - if (button is PinBoardState.PinBoardButton.Backspace) - state.onBackspaceLongClick - else null + if (button is PinBoardState.PinBoardButton.Backspace) + state.onBackspaceLongClick + else null, + minButtonSize = minButtonSize ) { Icon( modifier = Modifier.fillMaxSize(0.4f).aspectRatio(1f), @@ -78,7 +81,7 @@ fun PinBoard( } } is PinBoardState.PinBoardButton.Empty -> { - Spacer(Modifier.aspectRatio(1f).weight(1f).size(PinButtonDefaults.PinButtonMinSize)) + Spacer(Modifier.aspectRatio(1f).weight(1f).size(minButtonSize)) } } } diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinButton.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinButton.kt index 1d2f37c..c72be44 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinButton.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinButton.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.xinto.mauth.ui.component.Animatable import kotlinx.coroutines.CancellationException @@ -48,6 +49,7 @@ fun PrimaryPinButton( enabled: Boolean = true, colors: PinButtonColors = PinButtonDefaults.primaryPinButtonColors(), shapes: PinButtonShapes = PinButtonDefaults.plainPinButtonShapes(), + minButtonSize: Dp = PinButtonDefaults.PinButtonNormalMinSize, content: @Composable () -> Unit ) = PinButton( onClick = onClick, @@ -56,6 +58,7 @@ fun PrimaryPinButton( enabled = enabled, colors = colors, shapes = shapes, + minButtonSize = minButtonSize, content = content ) @@ -67,18 +70,19 @@ fun PinButton( enabled: Boolean = true, colors: PinButtonColors = PinButtonDefaults.plainPinButtonColors(), shapes: PinButtonShapes = PinButtonDefaults.plainPinButtonShapes(), + minButtonSize: Dp = PinButtonDefaults.PinButtonNormalMinSize, content: @Composable () -> Unit ) { val interactionSource = remember { MutableInteractionSource() } - val shape by shapes.getButtonShape(interactionSource) + val shape by shapes.getButtonShape(interactionSource, minButtonSize) val backgroundColor by colors.getBackgroundColor(interactionSource) val contentColor by colors.getForegroundColor(interactionSource) Box( modifier = modifier .aspectRatio(1f) .sizeIn( - minWidth = PinButtonDefaults.PinButtonMinSize, - minHeight = PinButtonDefaults.PinButtonMinSize, + minWidth = minButtonSize, + minHeight = minButtonSize, ) .graphicsLayer { clip = true @@ -106,7 +110,8 @@ fun PinButton( object PinButtonDefaults { - val PinButtonMinSize = 72.dp + val PinButtonSmallMinSize = 56.dp + val PinButtonNormalMinSize = 72.dp const val AnimationDurationPress = 200 const val AnimationDurationRelease = 150 @@ -190,14 +195,14 @@ data class PinButtonShapes( ) { @Composable - fun getButtonShape(interactionSource: InteractionSource): State { + fun getButtonShape(interactionSource: InteractionSource, minButtonSize: Dp = PinButtonDefaults.PinButtonNormalMinSize): State { val density = LocalDensity.current val size = with(density) { - val shapeSize = PinButtonDefaults.PinButtonMinSize.toPx() + val shapeSize = minButtonSize.toPx() Size(shapeSize, shapeSize) } - val animatable = remember(density, size) { + val animatable = remember(density, size, minButtonSize) { Animatable(shape, density, size) } return animatePressValue( diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt index 6d61bf4..2d43c5a 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt @@ -45,6 +45,7 @@ fun PinScaffold( contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets, description: (@Composable () -> Unit)? = null, error: Boolean = false, + useSmallButtons: Boolean = false, codeLength: Int, ) { Scaffold( @@ -59,14 +60,20 @@ fun PinScaffold( contentWindowInsets = contentWindowInsets, ) { val orientation = LocalConfiguration.current.orientation + val minButtonSize = remember(useSmallButtons) { + if (useSmallButtons) { + PinButtonDefaults.PinButtonSmallMinSize + } else { + PinButtonDefaults.PinButtonNormalMinSize + } + } if (orientation == Configuration.ORIENTATION_LANDSCAPE) { Row( modifier = Modifier .fillMaxWidth() .fillMaxHeight() .padding(it) - .padding(horizontal = 20.dp) - .padding(bottom = 16.dp), + .padding(horizontal = 20.dp), horizontalArrangement = Arrangement.SpaceAround, verticalAlignment = Alignment.CenterVertically ) { @@ -103,22 +110,21 @@ fun PinScaffold( ) } } - val pinBoardHorizontalPadding = 32.dp + val pinBoardHorizontalPadding = 16.dp val horizontalButtonSpace = 16.dp val totalPadding = (pinBoardHorizontalPadding * 2) + (horizontalButtonSpace * 2) - val maxBoxWidth = remember(PinButtonDefaults.PinButtonMinSize) { + val maxBoxWidth = remember(minButtonSize) { val buttonsInRow = 3 - (PinButtonDefaults.PinButtonMinSize * buttonsInRow) + totalPadding + (minButtonSize * buttonsInRow) + totalPadding } Box( - modifier = Modifier.sizeIn(maxWidth = maxBoxWidth), + modifier = Modifier.sizeIn(maxWidth = maxBoxWidth), contentAlignment = Alignment.Center ) { PinBoard( - modifier = Modifier - .padding(horizontal = pinBoardHorizontalPadding) - .padding(bottom = 16.dp), + modifier = Modifier.padding(horizontal = pinBoardHorizontalPadding), horizontalButtonSpace = horizontalButtonSpace, + minButtonSize = minButtonSize, state = state ) } diff --git a/app/src/main/java/com/xinto/mauth/ui/screen/pinremove/PinRemoveScreen.kt b/app/src/main/java/com/xinto/mauth/ui/screen/pinremove/PinRemoveScreen.kt index 2b57bc0..a608167 100644 --- a/app/src/main/java/com/xinto/mauth/ui/screen/pinremove/PinRemoveScreen.kt +++ b/app/src/main/java/com/xinto/mauth/ui/screen/pinremove/PinRemoveScreen.kt @@ -1,12 +1,15 @@ package com.xinto.mauth.ui.screen.pinremove +import android.content.res.Configuration import androidx.activity.compose.BackHandler import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -45,25 +48,25 @@ fun PinRemoveScreen( onNumberDelete: () -> Unit, onAllDelete: () -> Unit, ) { + val orientation = LocalConfiguration.current.orientation PinScaffold( codeLength = state.code.length, error = state is PinRemoveScreenState.Error, topBar = { - LargeTopAppBar( - title = { - Text(stringResource(R.string.pinremove_title)) - }, - navigationIcon = { - IconButton(onClick = onBack) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = null - ) - } - } - ) + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + TopAppBar( + title = { AppBarTitle() }, + navigationIcon = { AppBarNavigationIcon(onBack) } + ) + } else { + LargeTopAppBar( + title = { AppBarTitle() }, + navigationIcon = { AppBarNavigationIcon(onBack) } + ) + } }, description = null, + useSmallButtons = orientation == Configuration.ORIENTATION_LANDSCAPE, state = rememberPinBoardState( showEnter = true, onNumberClick = onNumberEnter, @@ -72,4 +75,19 @@ fun PinRemoveScreen( onBackspaceLongClick = onAllDelete ) ) +} + +@Composable +fun AppBarTitle() { + Text(stringResource(R.string.pinremove_title)) +} + +@Composable +fun AppBarNavigationIcon(onBack: () -> Unit) { + IconButton(onClick = onBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = null + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/xinto/mauth/ui/screen/pinsetup/PinSetupScreen.kt b/app/src/main/java/com/xinto/mauth/ui/screen/pinsetup/PinSetupScreen.kt index 03a7dd6..04ba7fc 100644 --- a/app/src/main/java/com/xinto/mauth/ui/screen/pinsetup/PinSetupScreen.kt +++ b/app/src/main/java/com/xinto/mauth/ui/screen/pinsetup/PinSetupScreen.kt @@ -1,5 +1,6 @@ package com.xinto.mauth.ui.screen.pinsetup +import android.content.res.Configuration import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContent import androidx.compose.animation.fadeIn @@ -9,8 +10,10 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -63,37 +66,25 @@ fun PinSetupScreen( onNumberDelete: () -> Unit, onAllDelete: () -> Unit, ) { + val orientation = LocalConfiguration.current.orientation PinScaffold( codeLength = code.length, error = error, topBar = { - LargeTopAppBar( - title = { - AnimatedContent( - targetState = state, - label = "PinSetupDescription", - transitionSpec = { - fadeIn() togetherWith fadeOut() - } - ) { - val resource = when (it) { - is PinSetupScreenState.Initial -> R.string.pinsetup_title_create - is PinSetupScreenState.Confirm -> R.string.pinsetup_title_confirm - } - Text(stringResource(resource)) - } - }, - navigationIcon = { - IconButton(onClick = onPrevious) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = null - ) - } - } - ) + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + TopAppBar( + title = { AppBarTitle(state) }, + navigationIcon = { AppBarNavigationIcon(onPrevious) } + ) + } else { + LargeTopAppBar( + title = { AppBarTitle(state) }, + navigationIcon = { AppBarNavigationIcon(onPrevious) } + ) + } }, description = null, + useSmallButtons = orientation == Configuration.ORIENTATION_LANDSCAPE, state = rememberPinBoardState( showEnter = true, onNumberClick = onNumberEnter, @@ -102,4 +93,31 @@ fun PinSetupScreen( onBackspaceLongClick = onAllDelete ) ) +} + +@Composable +fun AppBarTitle(state: PinSetupScreenState) { + AnimatedContent( + targetState = state, + label = "PinSetupDescription", + transitionSpec = { + fadeIn() togetherWith fadeOut() + } + ) { + val resource = when (it) { + is PinSetupScreenState.Initial -> R.string.pinsetup_title_create + is PinSetupScreenState.Confirm -> R.string.pinsetup_title_confirm + } + Text(stringResource(resource)) + } +} + +@Composable +fun AppBarNavigationIcon(onPrevious: () -> Unit) { + IconButton(onClick = onPrevious) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = null + ) + } } \ No newline at end of file From 0a6118ca2c9ab38729a8fb79d7e724074650c109 Mon Sep 17 00:00:00 2001 From: manpreet Date: Fri, 3 Jan 2025 16:16:30 -0700 Subject: [PATCH 4/4] Address feedback: Merge paddings. --- .../java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt index 2d43c5a..495e6ab 100644 --- a/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt +++ b/app/src/main/java/com/xinto/mauth/ui/component/pinboard/PinScaffold.kt @@ -136,8 +136,7 @@ fun PinScaffold( .fillMaxWidth() .fillMaxHeight() .padding(it) - .padding(40.dp) - .padding(bottom = 16.dp), + .padding(start = 40.dp, top = 40.dp, end = 40.dp, bottom = 56.dp), verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Bottom), horizontalAlignment = Alignment.CenterHorizontally ) {