1

这些天我面临着 Dismissible 组件的一个相当令人惊讶的行为。使用窄屏幕时,我在其自己的页面中使用了相同的小部件 AirportWidget:

    Scaffold(
      appBar: AppBar(…),
      body:  RefreshIndicator(
        key: _refreshIndicatorKey,
        child:  AirportWidget(…),
      onRefresh: _refreshAirportList)
    )

或者当在宽屏幕上显示时作为屏幕的右侧部分(右侧组件在一行中,组件列表占据左侧部分):

   Row(children: <Widget>[
     MyAirportsListWidget,
     ViewState.isLargeScreen ? Expanded(child: Card(child:AirportWidget(…)) : Container()])

现在我的问题是:我的 AirportWidget,在这两种情况下都是相同的 Widget,包含一列元素,每个元素都嵌入到 Dismissible 中。当 AirportWidget 显示在自己的页面上时,这一切都可以正常工作,但是当显示在宽屏幕的右侧时,它不会......它仍然以某种方式识别 Dismissible 元素何时向正确的方向滑动(当什么都不做在另一个方向滑动),但不是显示它在那个方向消失然后调用 onDismissed 方法,而是显示没有动画,只是跳到列的顶部(我猜是重建组件)。

从这里给某人敲钟,还是我需要提供完整的细节?

此致

更多代码细节:这是一个有点复杂的设计。包含 Dismissible 的 AirportWidget 本身由两个选项卡组成:第一个选项卡显示机场天气(现在与我们无关,因为它不包含 Dismissible),第二个选项卡显示 NOTAM(机场信息)。那是包含 Dismissible 元素的那个。



class AirportWidget extends StatefulWidget {

  Airport _airport;
  int _currentIndex;

  AirportWidget(this._airport, {int index, Key key}) : super(key: key) {
    _currentIndex =  index != null? index : ViewState.airportSelectedTabIndex;
  }

  @override
  AirportWidgetState createState() => AirportWidgetState();

}

class AirportWidgetState extends State<AirportWidget> {
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  // Bottom tabs and active tab index
  List<Widget> _children;

  @override
  void initState() {
    super.initState();

    _children = [
      AirportWeatherWidget(widget._airport),
      AirportNotamsWidget(widget._airport),
    ];
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      key: _scaffoldKey,
      body: widget._airport == null? noAirportScreen(context) : _children[widget._currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        unselectedItemColor: themes.AppColors.CREAM_FONT,
        onTap: onTabTapped, // new
        currentIndex: widget._currentIndex, // new
        items: [
          BottomNavigationBarItem(
            icon: new Icon(Icons.filter_drama),
            title: new Text('WEATHER'),
          ),
          BottomNavigationBarItem(
            icon: new Icon(Icons.library_books),
            title: new Text("NOTAMS"),
          ),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      ViewState.airportSelectedTabIndex = index;
      widget._currentIndex = index;
    });
  }
}

现在让我们看看包含 Dismissible 元素的 AirportNotamsWidget:

class AirportNotamsWidget extends StatefulWidget {

  Airport _airport;

  AirportNotamsWidget(this._airport);

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

class AirportNotamsWidgetState extends State<AirportNotamsWidget> {
 // final _scaffoldKey = GlobalKey<ScaffoldState>();  // used for snackbar display

  @override
  Widget build(BuildContext context) {
    List<Widget> notamsWidgetsList = List<Widget>();
    Color nonSelectedStarColor = Theme.of(context).brightness == Brightness.light?
    themes.AppColors.LIGHT_GREY : themes.AppColors.CREAM_FONT;
    Color selectedStarColor = Theme.of(context).brightness == Brightness.light?
    themes.AppColors.YELLOW : themes.AppColors.DARK_YELLOW;

    Widget topRow = Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Flexible(child: Text(widget._airport.name, style: Theme.of(context).textTheme.subtitle)),
        Row( children: [
          IconButton(icon: Icon(Icons.ac_unit, color: ViewState.dislplaySnowtams? Theme.of(context).accentColor :
          Theme.of(context).unselectedWidgetColor),
            onPressed: () {
              setState(() {
                ViewState.dislplaySnowtams = !ViewState.dislplaySnowtams;
              });
            }
          ),
          MaterialButton(child: Text(ViewState.displayRelevantNotamsOnly? "RLV" : "ALL"), minWidth: 40,
          onPressed: () {
            setState(() {
              ViewState.displayRelevantNotamsOnly = !ViewState.displayRelevantNotamsOnly;
            });
          }
        )
        ])
    ],);
    notamsWidgetsList.add(topRow);
    //     Text("NOTAMs view not yet implemented", style: Theme.of(context).textTheme.body1),


    notamsWidgetsList.add(Container(
      color: Theme.of(context).selectedRowColor,
      child: Row(children: [Text("NOTAMS", style: TextStyle(color:
      Theme.of(context).brightness == Brightness.light? themes.AppColors.LIGHT_GREY: themes.AppColors.CREAM_FONT,
        fontWeight: FontWeight.bold),)],
        mainAxisAlignment: MainAxisAlignment.center,),
      padding: EdgeInsets.only(left:0, top: 3, bottom: 3), margin: EdgeInsets.only(top: 15, bottom: 6),
    ));

    if(widget._airport.normalNotamsList.isNotEmpty) {
      for(int i = 0; i < widget._airport.normalNotamsList.length; i++) {
        NOTAM notam = widget._airport.normalNotamsList[i];
          notamsWidgetsList.add(
           Dismissible(
             // unique key in order to be able to remove the item from a sublist and add it to another
              key: Key(notam.key + DateTime.now().toString()),
              background: Container(
                alignment: AlignmentDirectional.centerEnd,
                child: Padding(
                  padding: EdgeInsets.fromLTRB(themes.DISMISSIBLE_TILES_BACKGROUND_LATERAL_PADDING, 0.0,
                    themes.DISMISSIBLE_TILES_BACKGROUND_LATERAL_PADDING, 0.0),
                  child: Column(children: [Text("NON"), Text("RELEVANT")], mainAxisAlignment: MainAxisAlignment.center,)
                ),
              ),
             child: Card(
               child: Container(
                child: Column(
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Expanded(child: Text(notam.id + " - " + notam.Subject + " " + notam.Modifier,
                          style: Theme.of(context).textTheme.subhead)),
                        IconButton(icon: Icon(Icons.star, color: notam.isStarred()?  selectedStarColor : nonSelectedStarColor),
                          onPressed: ()async {
                            setState(() {
                              widget._airport.toggleNotamStarred(notam);
                              PersistenceManager.updateNotam(notam);
                            });
                          }),
                      ]),
                    Text(ViewUtil.printNotamMessage(notam.message), style: Theme.of(context).textTheme.body1),
                    Row(children:
                    [Text("From: " + ViewUtil.printDate(context, notam.startDate) + " " + ViewUtil.printTime(context, notam.startDate)
                      + "  To: " + ViewUtil.printDate(context, notam.endDate) + " " + ViewUtil.printTime(context, notam.endDate),
                      style: Theme.of(context).textTheme.body2,)], mainAxisAlignment: MainAxisAlignment.end,),
                  ],
                  crossAxisAlignment: CrossAxisAlignment.start,
                ),
                 padding: EdgeInsets.all(10),
               ),
              ),
              direction: DismissDirection.endToStart,
              onDismissed: (direction) {
                print("DISMISSED");
                    setState(() {
                      widget._airport.normalNotamsList.remove(notam);
                      widget._airport.nonRelevantNotamsList.add(notam);
                      notam.priority = NOTAM.PRIORITY_IRRELEVANT;
                      Util.sortNotamList(widget._airport.nonRelevantNotamsList);
                      PersistenceManager.updateNotam(notam);
                    });
                }
              ),
            );
      }
      notamsWidgetsList.add(Divider());
    }

    if(!ViewState.displayRelevantNotamsOnly) {
      if(widget._airport.nonRelevantNotamsList.isNotEmpty) {
        notamsWidgetsList.add(Text("NON OPERATION RELEVANT NOTAMs"));
        widget._airport.nonRelevantNotamsList.forEach((notam) {
            notamsWidgetsList.add(
              Dismissible(
                // unique key in order to be able to remove the item from a sublist and add it to another
                  key: Key(notam.key + DateTime.now().toString()),
                  background: Container(
                    alignment: AlignmentDirectional.centerStart,
                    child: Padding(
                      padding: EdgeInsets.fromLTRB(themes.DISMISSIBLE_TILES_BACKGROUND_LATERAL_PADDING, 0.0,
                        themes.DISMISSIBLE_TILES_BACKGROUND_LATERAL_PADDING, 0.0),
                      child: Text("RELEVANT"),
                    ),
                  ),
                  child: Card(
                    child: Container(
                      child: Column(
                        children: [
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Expanded(child: Text(notam.id + " - " + notam.Subject + " " + notam.Modifier,
                                style: Theme.of(context).textTheme.subhead)),
                              IconButton(icon: Icon(Icons.star, color: notam.isStarred()?  selectedStarColor : nonSelectedStarColor),
                                onPressed: ()async {
                                  setState(() {
                                    widget._airport.toggleNotamStarred(notam);
                                    PersistenceManager.updateNotam(notam);
                                  });
                                }),
                            ]),
                          Text(ViewUtil.printNotamMessage(notam.message), style: Theme.of(context).textTheme.body1),
                          Row(children:
                          [Text("From: " + ViewUtil.printDate(context, notam.startDate) + " " + ViewUtil.printTime(context, notam.startDate)
                            + "  To: " + ViewUtil.printDate(context, notam.endDate) + " " + ViewUtil.printTime(context, notam.endDate),
                            style: Theme.of(context).textTheme.body2,)], mainAxisAlignment: MainAxisAlignment.end,),
                        ],
                        crossAxisAlignment: CrossAxisAlignment.start,
                      ),
                      padding: EdgeInsets.all(10),
                  )),
                  direction: DismissDirection.startToEnd,
                  onDismissed: (direction) {
                    if (direction == DismissDirection.startToEnd) {
                      setState(() {
                        widget._airport.nonRelevantNotamsList.remove(notam);
                        widget._airport.normalNotamsList.add(notam);
                        notam.priority = NOTAM.PRIORITY_NORMAL;
                        Util.sortNotamList(widget._airport.normalNotamsList);
                        PersistenceManager.updateNotam(notam);
                      });
                    }
                  }
                ),
);

        });
      }
    }
    return Builder(
      builder: (context) =>
        SingleChildScrollView(
          child: Container(
              padding: EdgeInsets.all(10),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.center,
                children: notamsWidgetsList,
              )
          )
        )
    );
  }
}

这是应用程序在“宽屏”模式下的截图:当我们在左侧列表中选择一个机场时,机场的两个选项卡的详细信息显示在屏幕的右半部分。在这里,我们可以看到 NOTAM 选项卡,其中包含有问题的 Dismissible 卡。

在此处输入图像描述

如下图在窄屏模式下显示时,相同的 Dismissible 卡可以正常工作

在此处输入图像描述

4

0 回答 0