Flutter中如何实现带不可删除固定前缀的TextField?
I've got you covered! Here's a straightforward way to implement a TextField with an unremovable fixed prefix, plus how to set a completely unchangeable fixed value if that's what you need.
1. Unremovable Prefix with Editable Content After
The key here is using a TextEditingController to monitor and enforce the fixed prefix. This ensures users can't delete or modify the prefix, but can type freely after it.
Full Code Example
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Fixed Prefix TextField')), body: const Padding( padding: EdgeInsets.all(16.0), child: FixedPrefixTextField(), ), ), ); } } class FixedPrefixTextField extends StatefulWidget { const FixedPrefixTextField({super.key}); @override State<FixedPrefixTextField> createState() => _FixedPrefixTextFieldState(); } class _FixedPrefixTextFieldState extends State<FixedPrefixTextField> { // Define your unremovable fixed prefix static const String _fixedPrefix = 'XXXXXXXXXXXX'; late TextEditingController _controller; @override void initState() { super.initState(); // Initialize controller with the fixed prefix _controller = TextEditingController(text: _fixedPrefix); // Add listener to enforce the prefix _controller.addListener(_enforceFixedPrefix); } void _enforceFixedPrefix() { final currentText = _controller.text; // Case 1: Text doesn't start with the fixed prefix (e.g., user deleted part of it) if (!currentText.startsWith(_fixedPrefix)) { // Reconstruct the text: keep the prefix + any valid content the user entered _controller.text = _fixedPrefix + currentText.replaceAll(_fixedPrefix, ''); // Move cursor to the end of the text _controller.selection = TextSelection.fromPosition( TextPosition(offset: _controller.text.length), ); } // Case 2: Cursor is positioned before the prefix (user tried to move it left) else if (_controller.selection.start < _fixedPrefix.length) { // Force cursor to stay after the prefix _controller.selection = TextSelection.fromPosition( TextPosition(offset: _fixedPrefix.length), ); } } @override void dispose() { // Don't forget to dispose the controller to avoid memory leaks _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return TextField( controller: _controller, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: 'Type something after the fixed prefix...', ), ); } }
How It Works
- Initialization: We start by setting the controller's initial text to the fixed prefix.
- Listener: The
_enforceFixedPrefixmethod runs every time the text changes:- If the text no longer starts with the prefix, we reset it to include the prefix plus any valid user input.
- If the user tries to move the cursor before the prefix, we automatically move it back to the end of the prefix, preventing edits in that area.
- Cleanup: We dispose the controller to avoid memory leaks.
2. Completely Unremovable Fixed Value
If you want a TextField with a fixed value that users can't modify at all (no edits allowed), you have two options:
Option A: Read-Only TextField
This is the simplest approach if you just want to display a fixed value without allowing edits:
TextField( controller: TextEditingController(text: 'Your Fixed Value'), readOnly: true, decoration: const InputDecoration(border: OutlineInputBorder()), )
Option B: Enforce Fixed Value with Controller
If you need the TextField to look editable but prevent any changes (even if users try to type/paste), use a controller listener that resets the text to the fixed value:
late TextEditingController _fixedValueController; @override void initState() { super.initState(); _fixedValueController = TextEditingController(text: 'Your Unchangeable Value'); _fixedValueController.addListener(() { if (_fixedValueController.text != 'Your Unchangeable Value') { _fixedValueController.text = 'Your Unchangeable Value'; } }); } // Then in your build method: TextField( controller: _fixedValueController, decoration: const InputDecoration(border: OutlineInputBorder()), )
This will revert any changes the user tries to make, keeping the fixed value intact.
内容的提问来源于stack exchange,提问作者ömer şahin

