Scaffold.of() 在显示小吃店颤动时使用不包含脚手架错误的上下文调用

Scaffold.of() called with a context that does not contain a Scaffold error when showing snack bar flutter

在我的屏幕上,我有一个 ScrollablePositionedList.builder,我正在使用 slidable 来滑动删除数据库中的记录,我弹出一个显示确认对话框,在用户确认删除后我想要显示一个用于撤消的小吃店。在添加确认对话框小吃店之前显示正常,但现在我得到 Scaffold.of() called with a context that does not contain a Scaffold.. 我需要在显示它之前调用 Navigator.pop(context) 以关闭确认对话框所以认为这是我尝试评论的原因它出来了,但我仍然得到错误。 你能发现我在这里做错了什么吗?我还想在 BlocLister 中收到 BookingDeleted 状态时显示小吃店,因为它在 Scaffold 树之前如何实现它? 一如既往,非常感谢您的帮助。 这是屏幕代码:

class _BookingsScreenState extends State<BookingsScreen> {
  dynamic backButton = Platform.isIOS ? CupertinoIcons.back : Icons.arrow_back;
  DateFormat dateOnlyFormat =
      DateFormat.yMMMMEEEEd(AppLocalizations.instance.text('Language code'));
  DateFormat timeFormat = DateFormat('Hm');
  AudioCache cache = new AudioCache();
  ItemScrollController scrollController = ItemScrollController();
  List<Booking> bookings = [];

  int cellIndex = 0;

  @override
  Widget build(BuildContext context) {
    cache.loadAll(['click.mp3', 'tableViewOpen.mp3', 'tableViewClose.mp3']);
    return BlocListener<BookingBloc, BookingState>(
      listener: (BuildContext context, BookingState state) {
        if (state is LoadedBookings) {
          setState(() {
            bookings = state.bookings;
            print(
                'BookingsScreen BlocListener we have  ${state.bookings.length} saved bookings');
            print(
                'BookingsScreen BlocListener saved bookings are ${state.bookings}');
            print(bookings);
          });
        }
        if (state is BookingDeleted) {
          showDialog(
            barrierDismissible: false,
            context: context,
            builder: (BuildContext context) {
              return BookingDeletedConfirmationDialog();
            }
          );
          Timer(Duration(milliseconds: 1500), (){
            cache.play('tableViewClose.mp3');
            Navigator.of(context, rootNavigator: false).pop(context);
          });
        }
      },
      child: Stack(
        children: [
          Image(
              image: widget.bgImage.image,
              height: MediaQuery.of(context).size.height,
              width: MediaQuery.of(context).size.width,
              fit: BoxFit.cover),
          Scaffold(
            backgroundColor: Colors.transparent,
            appBar: AppBar(
              elevation: 0,
              centerTitle: true,
              leading: IconButton(
                  icon: Icon(backButton),
                  color: Colors.redAccent,
                  onPressed: () {
                    cache.play('tableViewClose.mp3');
                    Navigator.pop(context);
                  }),
              title: Text(
                AppLocalizations.instance.text('BookingScreenTitle'),
                style: TextStyle(
                    color: Colors.orange,
                    fontSize: 22,
                    fontWeight: FontWeight.w500,
                    letterSpacing: 1),
              ),
              backgroundColor: Colors.transparent,
            ),
            body: SafeArea(
              minimum: EdgeInsets.symmetric(horizontal: 20),
              child: ScrollablePositionedList.builder(
                itemScrollController: scrollController,
                itemCount: bookings.length,
                itemBuilder: (BuildContext context, int index) => Slidable(
                  actionPane: SlidableBehindActionPane(),
                  actionExtentRatio: 0.25,
                  actions: <Widget>[
                    IconSlideAction(
                      caption:
                          AppLocalizations.instance.text('Booking details'),
                      color: Colors.transparent,
                      foregroundColor: Colors.blue,
                      icon: Icons.details,
                      onTap: () {
                        print('BookingDetailsScreen');
                      },
                    ),
                  ],
                  secondaryActions: <Widget>[
                    IconSlideAction(
                      caption: AppLocalizations.instance.text('Delete booking'),
                      color: Colors.transparent,
                      foregroundColor: Colors.red,
                      icon: Icons.delete,
                      onTap: () {
                        setState(() {
                          cellIndex = index;
                        });
                        var booking = bookings.elementAt(index);
                        if (booking.bookingState == 'Waiting' || booking.bookingState == 'Received' || booking.bookingState == 'Cancelled') {
                          showDialog(
                            context: context,
                            barrierDismissible: false,
                            builder: (BuildContext context) {
                              return BookingDeletionConfirmationDialog(
                                index: index,
                                booking: booking,
                                onPressedCancel: (){
                                  cache.play('tableViewClose.mp3');
                                  Navigator.pop(context);
                                  },
                                onPressedDelete: (){
                                  cache.play('tableViewClose.mp3');
                                  Navigator.pop(context);
                                  deleteItem(index, booking);
                                  //Scaffold.of() called with a context that does not contain a Scaffold. ???

                                  Scaffold.of(context).showSnackBar(SnackBar(
                                      backgroundColor: Colors.redAccent,
                                      content: Text(
                                        AppLocalizations.instance
                                            .text('Booking deleted'),
                                        style: TextStyle(color: Colors.white),
                                      ),
                                      action: SnackBarAction(
                                          textColor: Colors.white,
                                          label: AppLocalizations.instance.text('Undo'),
                                          onPressed: () {
                                            //To undo deletion
                                            undoDeletion(index, booking);
                                          })));
                                  },
                              );
                            }
                          );
                        } else {
                          Scaffold.of(context).showSnackBar(SnackBar(
                            backgroundColor: Colors.redAccent,
                            content: Text(
                              AppLocalizations.instance
                                  .text('Booking not deletable'),
                              style: TextStyle(color: Colors.white),
                            ),
                          ));
                        }
                      },
                    ),
                  ],
                  child: BookingCell(
                    isSelected: false,
                    borderColor: bookings[index].bookingState == 'Waiting'
                        ? Colors.blue
                        : bookings[index].bookingState == 'Received'
                            ? Colors.amber.shade200
                            : bookings[index].bookingState == 'Started'
                                ? Colors.amber.shade600
                                : bookings[index].bookingState == 'Completed'
                                    ? Colors.green.shade400
                                    : bookings[index].bookingState ==
                                            'Cancelled'
                                        ? Colors.redAccent
                                        : Colors.blueGrey.shade300,
                    worksList: bookings[index].worksNameList,
                    bookingId: bookings[index].bookingId.toString(),
                    bookingDate: dateOnlyFormat.format(
                        DateTime.fromMillisecondsSinceEpoch(
                            bookings[index].bookingDate)),
                    bookingStart: timeFormat.format(
                        DateTime.fromMillisecondsSinceEpoch(
                            bookings[index].bookingStart)),
                    shopName: bookings[index].shopName,
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  void deleteItem(index, Booking booking) {
    setState(() {
      BlocProvider.of<BookingBloc>(context).add(DeleteBooking(
          booking: booking,
          cityDb: widget.cityDb,
          regionDb: widget.regionDb,
          countryDb: widget.countryDb));
    });
    BlocProvider.of<BookingBloc>(context).add(UpdateBookingState(
        bookingId: booking.bookingId.toString(), state: 'Cancelled'));
  }

  void undoDeletion(index, Booking booking) {
    setState(() {
    booking.bookingState ='Reactivated.'+ booking.bookingState;


      BlocProvider.of<BookingBloc>(context).add(SaveBooking(
          booking: booking,
          cityDb: widget.cityDb,
          regionDb: widget.regionDb,
          countryDb: widget.countryDb));
    });
  }

}

使用脚手架全局密钥尝试此解决方案

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class _BookingsScreenState extends State<BookingsScreen> {
  dynamic backButton = Platform.isIOS ? CupertinoIcons.back : Icons.arrow_back;
  DateFormat dateOnlyFormat =
      DateFormat.yMMMMEEEEd(AppLocalizations.instance.text('Language code'));
  DateFormat timeFormat = DateFormat('Hm');
  AudioCache cache = new AudioCache();
  ItemScrollController scrollController = ItemScrollController();
  List<Booking> bookings = [];

  int cellIndex = 0;

  // scaffold global key
  GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    cache.loadAll(['click.mp3', 'tableViewOpen.mp3', 'tableViewClose.mp3']);
    return BlocListener<BookingBloc, BookingState>(
      listener: (BuildContext context, BookingState state) {
        if (state is LoadedBookings) {
          setState(() {
            bookings = state.bookings;
            print(
                'BookingsScreen BlocListener we have  ${state.bookings.length} saved bookings');
            print(
                'BookingsScreen BlocListener saved bookings are ${state.bookings}');
            print(bookings);
          });
        }
        if (state is BookingDeleted) {
          showDialog(
              barrierDismissible: false,
              context: context,
              builder: (BuildContext context) {
                return BookingDeletedConfirmationDialog();
              });
          Timer(Duration(milliseconds: 1500), () {
            cache.play('tableViewClose.mp3');
            Navigator.of(context, rootNavigator: false).pop(context);
          });
        }
      },
      child: Stack(
        children: [
          Image(
              image: widget.bgImage.image,
              height: MediaQuery.of(context).size.height,
              width: MediaQuery.of(context).size.width,
              fit: BoxFit.cover),
          Scaffold(
            // assign the key
            key: scaffoldKey,
            backgroundColor: Colors.transparent,
            appBar: AppBar(
              elevation: 0,
              centerTitle: true,
              leading: IconButton(
                  icon: Icon(backButton),
                  color: Colors.redAccent,
                  onPressed: () {
                    cache.play('tableViewClose.mp3');
                    Navigator.pop(context);
                  }),
              title: Text(
                AppLocalizations.instance.text('BookingScreenTitle'),
                style: TextStyle(
                    color: Colors.orange,
                    fontSize: 22,
                    fontWeight: FontWeight.w500,
                    letterSpacing: 1),
              ),
              backgroundColor: Colors.transparent,
            ),
            body: SafeArea(
              minimum: EdgeInsets.symmetric(horizontal: 20),
              child: ScrollablePositionedList.builder(
                itemScrollController: scrollController,
                itemCount: bookings.length,
                itemBuilder: (BuildContext context, int index) => Slidable(
                  actionPane: SlidableBehindActionPane(),
                  actionExtentRatio: 0.25,
                  actions: <Widget>[
                    IconSlideAction(
                      caption:
                          AppLocalizations.instance.text('Booking details'),
                      color: Colors.transparent,
                      foregroundColor: Colors.blue,
                      icon: Icons.details,
                      onTap: () {
                        print('BookingDetailsScreen');
                      },
                    ),
                  ],
                  secondaryActions: <Widget>[
                    IconSlideAction(
                      caption: AppLocalizations.instance.text('Delete booking'),
                      color: Colors.transparent,
                      foregroundColor: Colors.red,
                      icon: Icons.delete,
                      onTap: () {
                        setState(() {
                          cellIndex = index;
                        });
                        var booking = bookings.elementAt(index);
                        if (booking.bookingState == 'Waiting' ||
                            booking.bookingState == 'Received' ||
                            booking.bookingState == 'Cancelled') {
                          showDialog(
                              context: context,
                              barrierDismissible: false,
                              builder: (BuildContext context) {
                                return BookingDeletionConfirmationDialog(
                                  index: index,
                                  booking: booking,
                                  onPressedCancel: () {
                                    cache.play('tableViewClose.mp3');
                                    Navigator.pop(context);
                                  },
                                  onPressedDelete: () {
                                    cache.play('tableViewClose.mp3');
                                    Navigator.pop(context);
                                    deleteItem(index, booking);
                                    //Scaffold.of() called with a context that does not contain a Scaffold. ???

                                    scaffoldKey.currentState.showSnackBar(
                                        SnackBar(
                                            backgroundColor: Colors.redAccent,
                                            content: Text(
                                              AppLocalizations.instance
                                                  .text('Booking deleted'),
                                              style: TextStyle(
                                                  color: Colors.white),
                                            ),
                                            action: SnackBarAction(
                                                textColor: Colors.white,
                                                label: AppLocalizations.instance
                                                    .text('Undo'),
                                                onPressed: () {
                                                  //To undo deletion
                                                  undoDeletion(index, booking);
                                                })));
                                  },
                                );
                              });
                        } else {
                          scaffoldKey.currentState.showSnackBar(SnackBar(
                            backgroundColor: Colors.redAccent,
                            content: Text(
                              AppLocalizations.instance
                                  .text('Booking not deletable'),
                              style: TextStyle(color: Colors.white),
                            ),
                          ));
                        }
                      },
                    ),
                  ],
                  child: BookingCell(
                    isSelected: false,
                    borderColor: bookings[index].bookingState == 'Waiting'
                        ? Colors.blue
                        : bookings[index].bookingState == 'Received'
                            ? Colors.amber.shade200
                            : bookings[index].bookingState == 'Started'
                                ? Colors.amber.shade600
                                : bookings[index].bookingState == 'Completed'
                                    ? Colors.green.shade400
                                    : bookings[index].bookingState ==
                                            'Cancelled'
                                        ? Colors.redAccent
                                        : Colors.blueGrey.shade300,
                    worksList: bookings[index].worksNameList,
                    bookingId: bookings[index].bookingId.toString(),
                    bookingDate: dateOnlyFormat.format(
                        DateTime.fromMillisecondsSinceEpoch(
                            bookings[index].bookingDate)),
                    bookingStart: timeFormat.format(
                        DateTime.fromMillisecondsSinceEpoch(
                            bookings[index].bookingStart)),
                    shopName: bookings[index].shopName,
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  void deleteItem(index, Booking booking) {
    setState(() {
      BlocProvider.of<BookingBloc>(context).add(DeleteBooking(
          booking: booking,
          cityDb: widget.cityDb,
          regionDb: widget.regionDb,
          countryDb: widget.countryDb));
    });
    BlocProvider.of<BookingBloc>(context).add(UpdateBookingState(
        bookingId: booking.bookingId.toString(), state: 'Cancelled'));
  }

  void undoDeletion(index, Booking booking) {
    setState(() {
      booking.bookingState = 'Reactivated.' + booking.bookingState;

      BlocProvider.of<BookingBloc>(context).add(SaveBooking(
          booking: booking,
          cityDb: widget.cityDb,
          regionDb: widget.regionDb,
          countryDb: widget.countryDb));
    });
  }
}