I'm trying to build a pixel-perfect design in Flutter that includes a TextField. The design requires the label to behave like this:
- When the TextField is not focused and empty, the label should appear inside the input field as a placeholder.
- When the TextField is focused, the label should move just above the input text but still inside the border, not at the top-left edge of the TextField (the default floating label position).
I need: I need to design a pixel-perfect UI according to the design below:

But I'm currently having this:

The Problem: I have a prefix widget (like a country code selector for a phone number) that is always visible. Because of this, the label behaves as if the TextField is always focused — it's always displayed in its floating position, even when the field is not focused or filled.
Current Code What I've tried: Here is the code that I've tried to get the target design.
TextField(
keyboardType: TextInputType.phone,
scrollPadding: EdgeInsets.zero,
decoration: InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
label: Text(
'Phone number',
style: TextStyle(
color: AppColors.secondaryTextColor,
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
errorText: showError ? formState['phoneError'] : null,
errorMaxLines: 2,
errorStyle: const TextStyle(fontSize: 12),
// Content Padding
contentPadding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 12),
// Prefix for country code
prefix: IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
CountryCodePicker(
onChanged: (country) {
formNotifier.updateCountryCode(
country.dialCode ?? '+91', country.name ?? 'India');
},
textStyle: const TextStyle(
fontSize: 16,
color: AppColors.primaryTextColor,
fontWeight: FontWeight.w600,
),
initialSelection: formState['countryCode'],
favorite: const ['IN', 'BD', 'US'],
showFlag: false,
showDropDownButton: true,
alignLeft: false,
padding: EdgeInsets.zero,
flagWidth: 24,
builder: (country) => Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
country?.dialCode ?? '+91',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
Gap(8),
],
),
),
const VerticalDivider(
thickness: 1,
width: 1,
color: AppColors.defaultBorderColor,
),
const SizedBox(width: 8),
],
),
),
// Suffix Icons for validation
suffixIcon: showError
? const Icon(Icons.close, color: Colors.red)
: isValid
? const Icon(Icons.check, color: Colors.green)
: null,
// Borders
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
const BorderSide(color: AppColors.defaultBorderColor),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(
color: AppColors.darkBackgroundColor, width: 2),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
const BorderSide(color: AppColors.defaultBorderColor),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red, width: 1.5),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Colors.red, width: 2),
),
),
onChanged: (value) => formNotifier.updateField('phone', value),
)