@@ -4,10 +4,11 @@ import androidx.annotation.DrawableRes
44import androidx.compose.foundation.layout.Arrangement
55import androidx.compose.foundation.layout.Box
66import androidx.compose.foundation.layout.BoxScope
7+ import androidx.compose.foundation.layout.BoxWithConstraints
78import androidx.compose.foundation.layout.Column
89import androidx.compose.foundation.layout.fillMaxSize
910import androidx.compose.foundation.layout.fillMaxWidth
10- import androidx.compose.foundation.layout.heightIn
11+ import androidx.compose.foundation.layout.height
1112import androidx.compose.foundation.lazy.grid.GridCells
1213import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
1314import androidx.compose.material3.Icon
@@ -22,15 +23,21 @@ import androidx.compose.ui.res.painterResource
2223import androidx.compose.ui.res.stringResource
2324import androidx.compose.ui.text.style.TextAlign
2425import androidx.compose.ui.tooling.preview.Devices
26+ import androidx.compose.ui.tooling.preview.Devices.NEXUS_5
2527import androidx.compose.ui.tooling.preview.Preview
28+ import androidx.compose.ui.unit.Dp
2629import androidx.compose.ui.unit.dp
2730import androidx.compose.ui.unit.sp
2831import to.bitkit.R
2932import to.bitkit.ui.shared.util.clickableAlpha
3033import to.bitkit.ui.theme.AppThemeSurface
3134import to.bitkit.ui.theme.Colors
3235
33- private val buttonHeight = 75 .dp // 75 * 4 = 300 height
36+ private val maxKeyboardHeight = 300 .dp
37+ private val idealButtonHeight = 75 .dp
38+ private val minButtonHeight = 50 .dp
39+ private const val KEYBOARD_ROWS_NUMBER = 4
40+ private const val KEYBOARD_COLUMNS_NUMBER = 3
3441val keyButtonHaptic = HapticFeedbackType .VirtualKey
3542
3643@Composable
@@ -39,30 +46,51 @@ fun Keyboard(
3946 onClickBackspace : () -> Unit ,
4047 modifier : Modifier = Modifier ,
4148 isDecimal : Boolean = true,
49+ availableHeight : Dp ? = null,
4250) {
43- LazyVerticalGrid (
44- columns = GridCells .Fixed (3 ),
45- userScrollEnabled = false ,
46- modifier = modifier,
47- ) {
48- item { KeyTextButton (text = " 1" , onClick = onClick) }
49- item { KeyTextButton (text = " 2" , onClick = onClick) }
50- item { KeyTextButton (text = " 3" , onClick = onClick) }
51- item { KeyTextButton (text = " 4" , onClick = onClick) }
52- item { KeyTextButton (text = " 5" , onClick = onClick) }
53- item { KeyTextButton (text = " 6" , onClick = onClick) }
54- item { KeyTextButton (text = " 7" , onClick = onClick) }
55- item { KeyTextButton (text = " 8" , onClick = onClick) }
56- item { KeyTextButton (text = " 9" , onClick = onClick) }
57- item { KeyTextButton (text = if (isDecimal) " ." else " 000" , onClick = onClick) }
58- item { KeyTextButton (text = " 0" , onClick = onClick) }
59- item {
60- KeyIconButton (
61- icon = R .drawable.ic_backspace,
62- contentDescription = stringResource(R .string.common__delete),
63- onClick = onClickBackspace,
64- modifier = Modifier .testTag(" KeyboardButton_backspace" ),
65- )
51+ BoxWithConstraints (modifier = modifier) {
52+ val constraintsHeight = this .maxHeight
53+ val effectiveHeight = availableHeight ? : constraintsHeight
54+ val idealTotalHeight = idealButtonHeight * KEYBOARD_ROWS_NUMBER
55+
56+ val maxAllowedHeight = minOf(maxKeyboardHeight, effectiveHeight)
57+
58+ val buttonHeight = when {
59+ // If we have plenty of space, use ideal height
60+ maxAllowedHeight >= idealTotalHeight -> idealButtonHeight
61+ // If space is limited, calculate proportional height but ensure minimum
62+ maxAllowedHeight >= (minButtonHeight * KEYBOARD_ROWS_NUMBER ) -> maxAllowedHeight / KEYBOARD_ROWS_NUMBER
63+ // If extremely limited, use absolute minimum
64+ else -> minButtonHeight
65+ }
66+
67+ val totalKeyboardHeight = buttonHeight * KEYBOARD_ROWS_NUMBER
68+
69+ LazyVerticalGrid (
70+ columns = GridCells .Fixed (KEYBOARD_COLUMNS_NUMBER ),
71+ userScrollEnabled = false ,
72+ modifier = Modifier .height(totalKeyboardHeight),
73+ ) {
74+ item { KeyTextButton (text = " 1" , onClick = onClick, buttonHeight = buttonHeight) }
75+ item { KeyTextButton (text = " 2" , onClick = onClick, buttonHeight = buttonHeight) }
76+ item { KeyTextButton (text = " 3" , onClick = onClick, buttonHeight = buttonHeight) }
77+ item { KeyTextButton (text = " 4" , onClick = onClick, buttonHeight = buttonHeight) }
78+ item { KeyTextButton (text = " 5" , onClick = onClick, buttonHeight = buttonHeight) }
79+ item { KeyTextButton (text = " 6" , onClick = onClick, buttonHeight = buttonHeight) }
80+ item { KeyTextButton (text = " 7" , onClick = onClick, buttonHeight = buttonHeight) }
81+ item { KeyTextButton (text = " 8" , onClick = onClick, buttonHeight = buttonHeight) }
82+ item { KeyTextButton (text = " 9" , onClick = onClick, buttonHeight = buttonHeight) }
83+ item { KeyTextButton (text = if (isDecimal) " ." else " 000" , onClick = onClick, buttonHeight = buttonHeight) }
84+ item { KeyTextButton (text = " 0" , onClick = onClick, buttonHeight = buttonHeight) }
85+ item {
86+ KeyIconButton (
87+ icon = R .drawable.ic_backspace,
88+ contentDescription = stringResource(R .string.common__delete),
89+ onClick = onClickBackspace,
90+ buttonHeight = buttonHeight,
91+ modifier = Modifier .testTag(" KeyboardButton_backspace" ),
92+ )
93+ }
6694 }
6795 }
6896}
@@ -72,10 +100,12 @@ fun KeyIconButton(
72100 @DrawableRes icon : Int ,
73101 contentDescription : String? ,
74102 onClick : () -> Unit ,
103+ buttonHeight : Dp = idealButtonHeight,
75104 modifier : Modifier = Modifier ,
76105) {
77106 KeyButtonBox (
78107 onClick = onClick,
108+ buttonHeight = buttonHeight,
79109 modifier = modifier,
80110 ) {
81111 Icon (
@@ -89,15 +119,21 @@ fun KeyIconButton(
89119fun KeyTextButton (
90120 text : String ,
91121 onClick : (String ) -> Unit ,
122+ buttonHeight : Dp = idealButtonHeight,
92123 modifier : Modifier = Modifier ,
93124) {
94125 KeyButtonBox (
95126 onClick = { onClick(text) },
127+ buttonHeight = buttonHeight,
96128 modifier = modifier.testTag(" KeyboardButton_$text " ),
97129 ) {
98130 Text (
99131 text = text,
100- fontSize = 24 .sp,
132+ fontSize = when {
133+ buttonHeight < 60 .dp -> 20 .sp
134+ buttonHeight < 70 .dp -> 22 .sp
135+ else -> 24 .sp
136+ },
101137 textAlign = TextAlign .Center ,
102138 color = Colors .White ,
103139 )
@@ -107,6 +143,7 @@ fun KeyTextButton(
107143@Composable
108144private fun KeyButtonBox (
109145 onClick : () -> Unit ,
146+ buttonHeight : Dp ,
110147 modifier : Modifier = Modifier ,
111148 content : @Composable (BoxScope .() -> Unit ),
112149) {
@@ -115,8 +152,8 @@ private fun KeyButtonBox(
115152 content = content,
116153 contentAlignment = Alignment .Center ,
117154 modifier = modifier
118- .heightIn (buttonHeight)
119- .fillMaxSize ()
155+ .height (buttonHeight)
156+ .fillMaxWidth ()
120157 .clickableAlpha(0.2f ) {
121158 haptic.performHapticFeedback(keyButtonHaptic)
122159 onClick()
@@ -167,3 +204,17 @@ private fun Preview3() {
167204 }
168205 }
169206}
207+
208+ @Preview(showBackground = true , device = NEXUS_5 )
209+ @Composable
210+ private fun PreviewShortScreen () {
211+ AppThemeSurface {
212+ Column (modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement .Bottom ) {
213+ Keyboard (
214+ onClick = {},
215+ onClickBackspace = {},
216+ modifier = Modifier .fillMaxWidth(),
217+ )
218+ }
219+ }
220+ }
0 commit comments