I have the same problem but only on ios 18. I found a tempory fix. I use two textfield so I don't have to toggle the obscure text property
class PasswordField extends StatefulWidget {
final TextEditingController? controller;
final String? hintText;
final TextInputAction textInputAction;
const PasswordField({
super.key,
this.controller,
this.hintText,
this.textInputAction = TextInputAction.done,
});
@override
PasswordFieldState createState() => PasswordFieldState();
}
class PasswordFieldState extends State<PasswordField> {
late TextEditingController _controller;
final FocusNode _focusNode = FocusNode();
bool _isObscured = true;
@override
void initState() {
super.initState();
_controller = widget.controller ?? TextEditingController();
}
void _toggleVisibility() {
setState(() {
_isObscured = !_isObscured;
});
_focusNode.requestFocus(); // Keep keyboard open
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AutofillGroup(
child: Stack(
children: [
// Visible TextField
Visibility(
visible: !_isObscured,
maintainState: true,
child: TextField(
key: const ValueKey("visible_text_field"),
controller: _controller,
focusNode: _focusNode,
obscureText: false,
autofillHints: const [AutofillHints.password],
textInputAction: widget.textInputAction,
decoration: InputDecoration(
hintText: widget.hintText ?? "Enter your password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
// Obscured TextField
Visibility(
visible: _isObscured,
maintainState: true,
child: TextField(
key: const ValueKey("obscured_text_field"),
controller: _controller,
focusNode: _focusNode,
obscureText: true,
autofillHints: const [AutofillHints.password],
textInputAction: widget.textInputAction,
decoration: InputDecoration(
hintText: widget.hintText ?? "Enter your password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
// Visibility Toggle Button
Positioned(
right: 0,
top: 0,
bottom: 0,
child: IconButton(
focusNode: null,
icon: Icon(
_isObscured ? Icons.visibility_off : Icons.visibility,
),
onPressed: _toggleVisibility,
),
),
],
),
);
}
}