当用户单击“清除图标”按钮时如何删除TextField? (不仅清除TextField的文本)
用户故事
用户单击按钮以添加播放器。 (从技术角度讲,此按钮添加了TextField)
用户可以在文本字段上输入播放器的名称。
用户单击“清除图标”按钮以删除当前的TextField(与add函数相反)。
new ListView.builder(
padding: EdgeInsets.all(0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 5,
itemBuilder: (context, index) {
print(index);
return TextField(
maxLength: 20,
decoration: InputDecoration(
labelText: "Player ${index+1}",
counterText: "",
prefixIcon: const Icon(Icons.person),
suffixIcon: new IconButton(
icon: Icon(Icons.clear),
onPressed: () =>
setState(() {
this.dispose(); // -----Doesn't work----
})
),
),
);
}
),
例如,如果用户单击“清除按钮”,则在播放器4上设置“约翰”,然后删除播放器4的TextField。它将仅保留4个TextField
答案 0 :(得分:2)
我假设的事实:
解决方案:
如果您希望以上所有内容均成立,那么实际上您需要跟踪TextFields的TextEditingController
,而不是文本字段本身。这是因为TextField的值实际上存储在TextEditingController中(如果不为每个小部件提供该值,则会即时创建)。检查一下:
import 'package:flutter/material.dart';
// needs to be StatefulWidget, so we can keep track of the count of the fields internally
class PlayerList extends StatefulWidget {
const PlayerList({
this.initialCount = 5,
});
// also allow for a dynamic number of starting players
final int initialCount;
@override
_PlayerListState createState() => _PlayerListState();
}
class _PlayerListState extends State<PlayerList> {
int fieldCount = 0;
int nextIndex = 0;
// you must keep track of the TextEditingControllers if you want the values to persist correctly
List<TextEditingController> controllers = <TextEditingController>[];
// create the list of TextFields, based off the list of TextControllers
List<Widget> _buildList() {
int i;
// fill in keys if the list is not long enough (in case we added one)
if (controllers.length < fieldCount) {
for (i = controllers.length; i < fieldCount; i++) {
controllers.add(TextEditingController());
}
}
i = 0;
// cycle through the controllers, and recreate each, one per available controller
return controllers.map<Widget>((TextEditingController controller) {
int displayNumber = i + 1;
i++;
return TextField(
controller: controller,
maxLength: 20,
decoration: InputDecoration(
labelText: "Player $displayNumber",
counterText: "",
prefixIcon: const Icon(Icons.person),
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: () {
// when removing a TextField, you must do two things:
// 1. decrement the number of controllers you should have (fieldCount)
// 2. actually remove this field's controller from the list of controllers
setState(() {
fieldCount--;
controllers.remove(controller);
});
},
),
),
);
}).toList(); // convert to a list
}
@override
Widget build(BuildContext context) {
// generate the list of TextFields
final List<Widget> children = _buildList();
// append an 'add player' button to the end of the list
children.add(
GestureDetector(
onTap: () {
// when adding a player, we only need to inc the fieldCount, because the _buildList()
// will handle the creation of the new TextEditingController
setState(() {
fieldCount++;
});
},
child: Container(
color: Colors.blue,
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(
'add player',
style: TextStyle(
color: Colors.white,
),
),
),
),
),
);
// build the ListView
return ListView(
padding: EdgeInsets.all(0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: children,
);
}
@override
void initState() {
super.initState();
// upon creation, copy the starting count to the current count
fieldCount = widget.initialCount;
}
@override
void dispose() {
super.dispose();
}
@override
void didUpdateWidget(PlayerList oldWidget) {
super.didUpdateWidget(oldWidget);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
}
}
有了上述内容,您可以:
我认为这就是您在这里寻找的东西。
答案 1 :(得分:-1)
您可以拥有一个属性来检查用户是否单击了该按钮,并取决于您显示/隐藏TextField
的值。在下面,如果用户单击X按钮,则仅使用一个布尔属性,然后将hideField
设置为true,TextField
将被大小为零的小部件替换。
new ListView.builder(
padding: EdgeInsets.all(0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 5,
itemBuilder: (context, index) {
print(index);
bool hideField = false; // I added it here
return hideField ? SizedBox.shrink() : TextField(
maxLength: 20,
decoration: InputDecoration(
labelText: "Player ${index + 1}",
counterText: "",
prefixIcon: const Icon(Icons.person),
suffixIcon: new IconButton(
icon: Icon(Icons.clear),
onPressed: () =>
setState(() {
hideField = true; // Now it works
})
),
),
);
}
)