I’m working on a TextField
in Flutter and trying to achieve the following:
- Prefix Text Alignment: I want the prefix text (e.g., “To:”) to be visible at all times, even when the user hasn’t focused on the
TextField
. - Cursor Alignment: I want the cursor to appear on the same line as the prefix text, not higher or lower than the prefix.
- Hint Text: I also want the hint text (e.g., “Name, $Cashtag, Phone, Email”) to remain visible when the
TextField
is empty, but I don’t want the cursor or hint text to overlap with the prefix text.
What I’ve Tried:
- Using
prefixText
to display the prefix text, but this works only when theTextField
is focused and doesn’t align well with the cursor. - Using
prefixIcon
withPadding
andAlign
to try and adjust the alignment, but it causes the cursor and hint text to disappear. - I’ve also tried setting
cursorColor
,border: InputBorder.none
, and adjusting the padding to no avail.
Code:
TextField(
cursorColor: Colors.green, // Set the cursor color
decoration: InputDecoration(
hintText: 'Name, \$Cashtag, Phone, Email',
border: InputBorder.none, // Remove the border
prefixText: 'To ', // Prefix text before input
prefixStyle: TextStyle(
color: Colors.black, // Prefix text color
fontSize: 18, // Prefix text size
fontWeight: FontWeight.bold, // Prefix text weight
),
),
)
Full code (For Context):
// payment_details_screen.dart
import 'package:cashapp/utilities/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class PaymentDetailsScreen extends StatelessWidget {
const PaymentDetailsScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
SizedBox(
height: 8.h,
),
// Header with amount and bank selection
Padding(
padding: EdgeInsets.only(right: 12.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: const Icon(
Icons.close,
color: Colors.black,
size: 30,
),
onPressed: () => Navigator.pop(context),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'\$7,000',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Padding(
padding: EdgeInsets.only(left: 16.w),
child: InkWell(
onTap: () {
// Show bank selection
},
child: Row(
children: const [
Text(
'Cash Balance',
style: TextStyle(
color: gray2,
fontSize: 14,
),
),
Icon(Icons.keyboard_arrow_down,
color: Colors.grey),
],
),
),
),
],
),
ElevatedButton(
onPressed: () {
// Handle payment
},
style: ElevatedButton.styleFrom(
elevation: 0.0,
padding:
EdgeInsets.symmetric(horizontal: 24, vertical: 10),
backgroundColor: green3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
minimumSize:
Size(60, 32), // Set width to 60 and height to 32
),
child: const Text(
'Pay',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
],
),
),
Divider(
color: gray5,
thickness: 1.5,
height: 32.h,
),
// Input fields
const SizedBox(width: 16),
TextField(
cursorColor: green3, // Set the cursor color to green
decoration: InputDecoration(
hintText: 'Name, \$Cashtag, Phone, Email',
hintStyle: TextStyle(
color: Colors.grey), // Optional, for hint text color
border: InputBorder.none, // Remove the border
prefixText: 'To ', // Prefix text before input
prefixStyle: TextStyle(
color: Colors.black, // Prefix text color
fontSize: 18, // Prefix text size
fontWeight: FontWeight.bold, // Prefix text weight
),
),
),
Divider(
color: gray5,
thickness: 1.5,
height: 32.h,
),
// Input fields
TextField(
cursorColor: green3, // Set the cursor color to green
decoration: InputDecoration(
hintText: 'Name, \$Cashtag, Phone, Email',
border: InputBorder.none, // Remove the border
prefixText: 'For ', // Prefix text before input
prefixStyle: TextStyle(
color: Colors.black, // Prefix text color
fontSize: 18, // Prefix text size
fontWeight: FontWeight.bold, // Prefix text weight
),
),
),
// Payment type selector
SingleChildScrollView(
scrollDirection:
Axis.horizontal, // Make the row scrollable horizontally
child: Row(
children: [
const Text('Send as'),
const SizedBox(width: 16),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF24CE84),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
child: const Text('Cash'),
),
const SizedBox(width: 8),
OutlinedButton(
onPressed: () {},
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
child: Row(
children: const [
Text('Gift Card'),
Icon(Icons.keyboard_arrow_down),
],
),
),
const SizedBox(width: 8),
OutlinedButton(
onPressed: () {},
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
child: Row(
children: const [
Text('Stock'),
Icon(Icons.keyboard_arrow_down),
],
),
),
const SizedBox(width: 8),
OutlinedButton(
onPressed: () {},
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
child: Row(
children: const [
Text('Stock'),
Icon(Icons.keyboard_arrow_down),
],
),
),
],
),
),
// Suggested contacts
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'SUGGESTED',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
const SizedBox(height: 16),
_buildContactTile(
'J',
'Jay Z',
'\$sc',
Colors.brown,
isSelected: true,
),
_buildContactTile(
'D',
'Diego',
'\$dm',
Colors.purple,
),
_buildContactTile(
'S',
'Sandy G.',
'\$sandy',
Colors.deepOrange,
),
_buildContactTile(
'J',
'Diego Martinez',
'\$dm',
Colors.purple,
),
],
),
],
),
),
);
}
Widget _buildContactTile(
String initial,
String name,
String tag,
Color avatarColor, {
bool isSelected = false,
}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
children: [
SizedBox(
width: 24,
height: 24,
child: Checkbox(
value: isSelected,
onChanged: (value) {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
),
),
const SizedBox(width: 12),
CircleAvatar(
backgroundColor: avatarColor,
child: Text(
initial,
style: const TextStyle(color: Colors.white),
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(
tag,
style: const TextStyle(color: Colors.grey),
),
],
),
),
const Icon(Icons.person_outline),
],
),
);
}
}
What I’m trying to achieve:
Full Screen(For context):
Problem:
- The prefix text doesn’t stay visible when the
TextField
is focused, and when it does appear, it’s not properly aligned with the cursor. - The cursor is not appearing at the same level as the prefix text, causing misalignment.
How can I properly align the prefix text with the cursor, and ensure the prefix text stays visible even when the user is not focused on the TextField
?
Discover more from TrendyShopToBuy
Subscribe to get the latest posts sent to your email.