Flutter 从带有Bloc的ListView中删除特定项

Flutter 从带有Bloc的ListView中删除特定项,flutter,listview,dart,focus,bloc,Flutter,Listview,Dart,Focus,Bloc,我有一个包含ListView的页面,其中包含TextFormFields。用户可以从该列表视图中添加或删除项目。 我使用bloc模式,将ListView中的项目数量及其内容绑定到以bloc状态保存的列表中。当我想删除这些项目时,我会从这个列表中删除相应的文本并产生新的状态。但是,这将始终删除最后一项,而不是应该删除的项。在调试过程中,我可以清楚地看到我想要删除的项目实际上已从状态列表中删除。不过,ListView会删除最后一项 我读过,使用钥匙解决了这个问题,确实如此。但是,如果我使用密钥,则会

我有一个包含ListView的页面,其中包含TextFormFields。用户可以从该列表视图中添加或删除项目。 我使用bloc模式,将ListView中的项目数量及其内容绑定到以bloc状态保存的列表中。当我想删除这些项目时,我会从这个列表中删除相应的文本并产生新的状态。但是,这将始终删除最后一项,而不是应该删除的项。在调试过程中,我可以清楚地看到我想要删除的项目实际上已从状态列表中删除。不过,ListView会删除最后一项

我读过,使用钥匙解决了这个问题,确实如此。但是,如果我使用密钥,则会出现新问题。 现在,每次写入字符时,TextFormField都会失去焦点。我想这是因为ListView在每次键入字符时都会重新绘制其项,而且有一个键会使焦点的行为有所不同

有什么办法解决这个问题吗

页面代码(列表视图在底部):

类GiveBeneftis扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
var bloc=BlocProvider.of(上下文);
返回BlocBuilder(
生成器:(上下文、状态){
返回CreatePageTemplate(
进展:状态。创造的进展,
按钮栏:导航按钮(
onPressPrevious:(){
集团增加(创造进度变更(资产净值方向:-1));
Navigator.of(context.pop();
},
onPressNext:(){
集团增加(创造进度变更(资产净值方向:1));
Navigator.of(context.pushNamed(“创建挑战/添加图片”);
},
上一篇:'细节',
下一个:'图片',
),
子:列(
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
正文(
“列出挑战的好处”,
textAlign:textAlign.center,
样式:TextStyle(fontSize:28,fontWeight:fontWeight.bold),
),
尺寸箱(高度:30),
正文(
“可选:列出参与者可以预期的身体和精神益处。”,
textAlign:textAlign.center,
样式:TextStyle(
颜色:颜色。灰色,
尺寸:14,
fontWeight:fontWeight.w400),
),
尺寸箱(高度:50),
容器(
边距:所有边集(8.0),
装饰:盒子装饰(
边界半径:边界半径。圆形(12),
颜色:颜色。黄色[600]),
孩子:扁平按钮(
MaterialTargetSize:MaterialTargetSize.shrinkWrap,
onPressed:()=>bloc.add(ChallengeBenefitAdded()),
子项:文本('添加福利',
样式:TextStyle(
颜色:Colors.white,fontwweight:fontwweight.bold),
),
),
扩大(
子项:新建ListView.builder(
itemCount:state.benefits.length,
itemBuilder:(构建上下文,int i){
最终项目=国家福利[i];
返回填充(
填充:边缘组。对称(水平:25),
孩子:TextFieldTile(
//键:UniqueKey(),
labelText:'Benefit${i+1}',
验证程序:null,
initialText:state.benefits[i],
onTextChanged:(值)=>bloc.add(
挑战者已经改变了(
编号:i,文本:值),
onCancelIconClicked:(){
集团添加(已删除ChallengeBeneFit(编号:i));
},
));
})),
],
),
);
});
}
}
TextfieldTile的代码:

class TextFieldTile扩展了无状态小部件{
改变了最终函数ontext;
最终函数onCancelIconClicked;
最终功能验证器;
最终字符串标签文本;
最后一个字符串initialText;
常量文本字段(
{键,
这个.ontext改变了,
这个.oncanceliconclick,
这是labelText,
这篇文章,
此验证程序(0.validator})
:super(key:key);
@凌驾
小部件构建(构建上下文){
返回堆栈(子级:[
TextFormField(
text大写:text大写。句子,
initialValue:initialText,
验证器:验证器,
onChanged:onTextChanged,
maxLines:null,
装饰:输入装饰(
labelText:labelText,
)),
对齐(
对齐:alignment.topRight,
孩子:我的钮扣(
图标:图标(Icons.cancel),按下: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);
    }
if(事件为ChallengeBenefitAdded){
var newBenefitsList=List.from(state.benefits);
新受益人名单。添加(“”);
收益状态。copyWith(收益:newBenefitsList);
}
else if(事件为ChallengeBenefitChanged){
var newBenefitsList=List.from(state.benefits);
newBenefitsList[event.number]=event.text;
收益状态。copyWith(收益:newBenefitsList);
}
else if(事件已移除){
var newBenefitsList=List.from(state.benefits);
newBenefitsList.removeAt(事件编号);
收益状态。copyWith(收益:newBenefitsList);
}

我想你可以在这里做两件事

  • 创建一个不同的组来处理文本字段中的更改,这将避免
    BlocBuilder<CreateChallengeBloc, CreateChallengeState>(
        buildWhen: (previousState, currentState) {
            return (currentState is YourNonKeyboardStates);
         }
         ...
    );