diff --git a/android/app/src/main/java/org/bitcoinppl/cove/flows/SendFlow/EnterAmountView.kt b/android/app/src/main/java/org/bitcoinppl/cove/flows/SendFlow/EnterAmountView.kt
index cf6f504b1..b9dbe2675 100644
--- a/android/app/src/main/java/org/bitcoinppl/cove/flows/SendFlow/EnterAmountView.kt
+++ b/android/app/src/main/java/org/bitcoinppl/cove/flows/SendFlow/EnterAmountView.kt
@@ -17,6 +17,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -29,8 +30,10 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -62,6 +65,13 @@ fun EnterAmountView(
var textWidth by remember { mutableStateOf(0.dp) }
var isFocused by remember { mutableStateOf(false) }
+ // fall back to a local FocusRequester so the clickable wrapper can always
+ // programmatically focus the TextField even when the parent doesn't pass one
+ val localFocusRequester = remember { FocusRequester() }
+ val effectiveFocusRequester = focusRequester ?: localFocusRequester
+
+ val showTapPlaceholder = !isFocused && (amount.isEmpty() || amount == "0")
+
// offset to compensate for unit dropdown (matches iOS)
val configuration = LocalConfiguration.current
val screenWidthDp = configuration.screenWidthDp.dp
@@ -98,7 +108,16 @@ fun EnterAmountView(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.Bottom,
) {
- Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) {
+ Box(
+ modifier =
+ Modifier
+ .weight(1f)
+ // extend the tap target beyond the text glyphs and provide
+ // a ripple; BasicTextField still consumes taps within its
+ // own bounds, so this only fires for taps on empty space
+ .clickable { effectiveFocusRequester.requestFocus() },
+ contentAlignment = Alignment.Center,
+ ) {
AutoSizeTextField(
value = amount,
onValueChange = { newValue ->
@@ -118,18 +137,44 @@ fun EnterAmountView(
},
maxFontSize = 48.sp,
minimumScaleFactor = 0.01f,
- color = if (exceedsBalance) CoveColor.WarningOrange else MaterialTheme.colorScheme.onSurface,
+ color =
+ when {
+ // hide the default "0" value behind the placeholder so
+ // we don't see both at once
+ showTapPlaceholder -> Color.Transparent
+ exceedsBalance -> CoveColor.WarningOrange
+ else -> MaterialTheme.colorScheme.onSurface
+ },
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 30.dp).offset(x = amountOffset),
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 30.dp)
+ .offset(x = amountOffset)
+ // remove from accessibility tree when hidden behind
+ // the placeholder so TalkBack doesn't announce both
+ .then(
+ if (showTapPlaceholder) Modifier.clearAndSetSemantics {} else Modifier,
+ ),
onTextWidthChanged = { width -> textWidth = width },
onFocusChanged = { focused ->
isFocused = focused
onFocusChanged(focused)
},
keyboardActions = KeyboardActions(onDone = { onDone() }),
- focusRequester = focusRequester,
+ focusRequester = effectiveFocusRequester,
)
+
+ if (showTapPlaceholder) {
+ Text(
+ text = stringResource(R.string.placeholder_tap_to_enter_amount),
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ fontSize = 16.sp,
+ fontWeight = FontWeight.Medium,
+ modifier = Modifier.offset(x = amountOffset),
+ )
+ }
}
// unit dropdown area (only shown when in BTC mode, matches iOS)
if (!isFiatMode) {
@@ -174,6 +219,11 @@ fun EnterAmountView(
}
}
Spacer(Modifier.height(8.dp))
+ HorizontalDivider(
+ color = MaterialTheme.colorScheme.outlineVariant,
+ thickness = 1.dp,
+ )
+ Spacer(Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center,
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index ec77961ea..3f522c097 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -98,6 +98,7 @@
Balance
Enter amount
How much would you like to send?
+ Tap to enter amount
Enter address
Where do you want to send to?
Account