如何解决使用Bloc从ListView中删除特定项目
我有一个包含ListView的页面,其中包含TextFormFields。用户可以从该ListView添加或删除项目。 我使用了bloc模式,并将ListView中的Items数量及其内容绑定到以bloc状态保存的列表。当我想删除项目时,我从该列表中删除相应的文本并产生新状态。但是,这将始终删除最后一个项目,而不是应该删除的项目。调试时,我可以清楚地看到我要删除的项目实际上已从状态列表中删除。尽管如此,ListView还是删除了最后一个项目。
我已经读到使用键可以解决此问题,并且可以解决。但是,如果我使用按键,则会出现新问题。 现在,每次写入字符时,TextFormField都会失去焦点。我猜想这与以下事实有关:每次键入一个字符时,ListView都会重绘其项,并且以某种方式拥有键会使焦点的行为有所不同。
有什么办法解决这个问题吗?
页面代码(ListView在底部):
class GiveBeneftis extends StatelessWidget {
@override
Widget build(BuildContext context) {
var bloc = BlocProvider.of<CreateChallengeBloc>(context);
return BlocBuilder<CreateChallengeBloc,CreateChallengeState>(
builder: (context,state) {
return CreatePageTemplate(
progress: state.progressOfCreation,buttonBar: NavigationButtons(
onPressPrevious: () {
bloc.add(ProgressOfCreationChanged(nav_direction: -1));
Navigator.of(context).pop();
},onPressNext: () {
bloc.add(ProgressOfCreationChanged(nav_direction: 1));
Navigator.of(context).pushNamed("create_challenge/add_pictures");
},previous: 'Details',next: 'Picture',),child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,children: <Widget>[
Text(
'List the benefits of you Challenge',textAlign: TextAlign.center,style: TextStyle(fontSize: 28,fontWeight: FontWeight.bold),SizedBox(height: 30),Text(
'Optionally: Make a list of physical and mental benefits the participants can expect. ',style: TextStyle(
color: Colors.grey,fontSize: 14,fontWeight: FontWeight.w400),SizedBox(height: 50),Container(
margin: EdgeInsets.all(8.0),decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),color: Colors.yellow[600]),child: FlatButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,onPressed: () => bloc.add(ChallengeBenefitAdded()),child: Text('Add a benefit',style: TextStyle(
color: Colors.white,fontWeight: FontWeight.bold)),Expanded(
child: new ListView.builder(
itemCount: state.benefits.length,itemBuilder: (BuildContext context,int i) {
final item = state.benefits[i];
return Padding(
padding: EdgeInsets.symmetric(horizontal: 25),child: TextFieldTile(
//key: UniqueKey(),labelText: 'Benefit ${i + 1}',validator: null,initialText: state.benefits[i],onTextChanged: (value) => bloc.add(
ChallengeBenefitChanged(
number: i,text: value)),onCancelIconClicked: () {
bloc.add(ChallengeBenefitRemoved(number: i));
},));
})),],);
});
}
}
TextfieldTile的代码:
class TextFieldTile extends StatelessWidget {
final Function onTextChanged;
final Function onCancelIconClicked;
final Function validator;
final String labelText;
final String initialText;
const TextFieldTile(
{Key key,this.onTextChanged,this.onCancelIconClicked,this.labelText,this.initialText,this.validator})
: super(key: key);
@override
Widget build(BuildContext context) {
return Stack(children: <Widget>[
TextFormField(
textCapitalization: TextCapitalization.sentences,initialValue: initialText,validator: validator,onChanged: onTextChanged,maxLines: null,decoration: InputDecoration(
labelText: labelText,)),Align(
alignment: Alignment.topRight,child: IconButton(
icon: Icon(Icons.cancel),onPressed: onCancelIconClicked),]);
}
}
集团的相关部分:
if (event is ChallengeBenefitAdded) {
var newBenefitsList = List<String>.from(state.benefits);
newBenefitsList.add("");
yield state.copyWith(benefits: newBenefitsList);
}
else if (event is ChallengeBenefitChanged) {
var newBenefitsList = List<String>.from(state.benefits);
newBenefitsList[event.number] = event.text;
yield state.copyWith(benefits: newBenefitsList);
}
else if (event is ChallengeBenefitRemoved) {
var newBenefitsList = List<String>.from(state.benefits);
newBenefitsList.removeAt(event.number);
yield state.copyWith(benefits: newBenefitsList);
}
解决方法
我想到了您可以在这里做的两件事。
- 在文本字段中创建一个不同的块来处理更改,这将避免在不需要时实际上不必更新整个列表的状态。
- 有一个条件,可避免在您的集团更改为仅与键盘操作相关的状态时重建列表。
示例:
BlocBuilder<CreateChallengeBloc,CreateChallengeState>(
buildWhen: (previousState,currentState) {
return (currentState is YourNonKeyboardStates);
}
...
);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。