Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 删除项后ListView.builder中的UI更改_Flutter_Dart - Fatal编程技术网

Flutter 删除项后ListView.builder中的UI更改

Flutter 删除项后ListView.builder中的UI更改,flutter,dart,Flutter,Dart,我有一个statefulwidget(容器)列表。这些容器描述课程的参与者 用户可以通过单击按钮删除这些参与者 由于列表是作为流直接从Firestore检索的,因此单击FlatButton并删除时会有一点延迟 在这种情况下,我想禁用该按钮,直到移除该容器。为此,我使用吸收指针包装容器,并使用在设置状态中更改的布尔值编辑吸收参数的值 该问题在更新列表后发生。特定容器的吸收值保持为真。因此,用户不能删除旧的已删除参与者列表中的其他参与者 在参与者列表长度减少后,如何将禁用的值重置为假 class _

我有一个statefulwidget(容器)列表。这些容器描述课程的参与者

用户可以通过单击按钮删除这些参与者

由于列表是作为流直接从Firestore检索的,因此单击FlatButton并删除时会有一点延迟

在这种情况下,我想禁用该按钮,直到移除该容器。为此,我使用吸收指针包装容器,并使用在设置状态中更改的布尔值编辑吸收参数的值

该问题在更新列表后发生。特定容器的吸收值保持为。因此,用户不能删除旧的已删除参与者列表中的其他参与者

在参与者列表长度减少后,如何将禁用的值重置为

class _ParticipantList extends StatelessWidget {
  final CourseEventFormBloc courseEventFormBloc;

  const _ParticipantList({
    Key key,
    this.courseEventFormBloc,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CourseEventFormBloc, CourseEventFormState>(
      builder: (context, state) {
        return Expanded(
          child: ListView.builder(
            itemCount: state.participants.length,
            itemBuilder: (context, index) {
              return _ParticipantContainer(
                index: index,
                courseEventFormBloc: courseEventFormBloc,
              );
            },
          ),
        );
      },
    );
  }
}

class _ParticipantContainer extends StatefulWidget {
  final CourseEventFormBloc courseEventFormBloc;
  final int index;
  const _ParticipantContainer({
    Key key,
    @required this.index,
    @required this.courseEventFormBloc,
  }) : super(key: key);

  @override
  __ParticipantContainerState createState() => __ParticipantContainerState();
}

class __ParticipantContainerState extends State<_ParticipantContainer> {
  bool disabled = false;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CourseEventFormBloc, CourseEventFormState>(
      builder: (context, state) {
        print('${widget.index} - disabled:$disabled');
        return AbsorbPointer(
          absorbing: disabled,
          child: Container(
            margin: const EdgeInsets.symmetric(vertical: 4.0),
            decoration: BoxDecoration(
              color: Colors.blueGrey.shade100,
              borderRadius: BorderRadius.all(Radius.circular(13)),
            ),
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height * 0.07,
            alignment: Alignment.center,
            child: Stack(
              // mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Align(
                  alignment: Alignment.center,
                  child: Text(state.participants[widget.index].name),
                ),
                SizedBox(width: 20.0),
                Align(
                  alignment: Alignment.centerLeft,
                  child: FlatButton(
                    onPressed: () {
                      // through this AlertDialog I can delete a participant
                      // showAlertDialog(context, index, state.participants[index]);
                      showDialog(
                          context: context,
                          builder: (BuildContext context) {
                            return AlertDialog(
                              //! I might get an error for the Bloc since the Dialog has another context
                              title: BlocBuilder<CourseEventFormBloc,
                                  CourseEventFormState>(
                                cubit: widget.courseEventFormBloc,
                                builder: (context, state) {
                                  return Text(state.participants.isNotEmpty
                                      ? state.participants[widget.index].name
                                      : '');
                                },
                              ),
                              content:
                                  Text('Möchtest du den Teilnehmer entfernen?'),
                              actions: <Widget>[
                                FlatButton(
                                  onPressed: () => Navigator.pop(context),
                                  child: Text(
                                    'nein',
                                    style: TextStyle(color: kDarkRosaColor),
                                  ),
                                ),
                                FlatButton(
                                  onPressed: () {
                                    widget.courseEventFormBloc.add(
                                      CourseEventAdminParticipantDeleted(
                                        widget.index,
                                        state.participants[widget.index],
                                        state.courseEventObject,
                                      ),
                                    );
                                    setState(() {
                                      disabled = true;
                                    });
                                    Navigator.pop(context);
                                  },
                                  child: Text(
                                    'ja',
                                    style: TextStyle(color: kDarkRosaColor),
                                  ),
                                ),
                              ],
                            );
                          });
                    },
                    child: Container(
                      // margin: const EdgeInsets.only(right: 27.0),
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(100),
                          border: Border.all(width: 2, color: kDarkRosaColor)),
                      child: Icon(
                        Icons.delete,
                        color: kDarkRosaColor,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

为每个列表项生成一个键,以防止框架重用错误的状态

事实上,这正是非全局键的目的:区分在和解过程中无法区分的子项

键可以通过
ValueKey()
participant
数据库中的任何类似UUID的属性(参与者ID,或简称名称)生成

@覆盖
小部件构建(构建上下文){
返回BlocBuilder(
生成器:(上下文、状态){
扩大回报(
子项:ListView.builder(
itemCount:state.participants.length,
itemBuilder:(上下文,索引){
返回参与者容器(
key:ValueKey(state.participants[index].id),//基于UUID生成ValueKey
index:index,//也许您应该传递整个参与者,而不是索引
courseEventFormBloc:courseEventFormBloc,
);
},
),
);
},
);
}

覆盖
didUpdateWidget
适用于您的特殊情况。但是请记住,如果任何祖先在您的网络请求中触发了重建,那么将调用
didUpdateWidget
。因此。
AbsorbPointer
可能比您预期的更早被禁用,这是有风险的。

为每个列表项生成一个键,以防止框架重用错误的状态

事实上,这正是非全局键的目的:区分在和解过程中无法区分的子项

键可以通过
ValueKey()
participant
数据库中的任何类似UUID的属性(参与者ID,或简称名称)生成

@覆盖
小部件构建(构建上下文){
返回BlocBuilder(
生成器:(上下文、状态){
扩大回报(
子项:ListView.builder(
itemCount:state.participants.length,
itemBuilder:(上下文,索引){
返回参与者容器(
key:ValueKey(state.participants[index].id),//基于UUID生成ValueKey
index:index,//也许您应该传递整个参与者,而不是索引
courseEventFormBloc:courseEventFormBloc,
);
},
),
);
},
);
}

覆盖
didUpdateWidget
适用于您的特殊情况。但是请记住,如果任何祖先在您的网络请求中触发了重建,那么将调用
didUpdateWidget
。因此。
AbsorbPointer
可能比您预期的更早被禁用,这是有风险的。

因为我使用的是
Bloc
,最后,我在state类中添加了一个
字符串deleteded
。当我删除一个参与者时,我只是将他的
uid
传递到新产生的状态

此外,我去掉了有状态的小部件,我正在执行以下检查,以禁止对刚刚删除的参与者进行单击

state.deleteId==state.participants[index].uid,


@First_Strike推荐的方法同样有效,只是他会使用另一个状态管理(有状态的小部件而不是Bloc)。

因为我使用的是
Bloc
,最后,我在state类中添加了一个
字符串deletedId
。当我删除一个参与者时,我只是将他的
uid
传递到新产生的状态

此外,我去掉了有状态的小部件,我正在执行以下检查,以禁止对刚刚删除的参与者进行单击

state.deleteId==state.participants[index].uid,


@First_Strike推荐的方法也有类似的效果,只是他会使用另一个状态管理(有状态的小部件而不是Bloc)。

你不能创建一个回调,即当删除完成时。在该回调函数中,您可以使用setState并再次将false指定给禁用的?您不能创建一个回调,即当删除完成时。在该回调函数中,您可以使用setState,然后再次将false指定给禁用的?我更新了答案以演示如何使用键。我更新了答案以演示如何使用键。
@override
  void didUpdateWidget(covariant _ParticipantContainer oldWidget) {
    super.didUpdateWidget(oldWidget);
    disabled = false;
  }