Flutter Navigator.pop() 使对话框部分可见并带有黑色阴影背景

Flutter Navigator.pop() keeps the Dialog Box partially visible with black shadow background

抱歉解释得太长了,但我想我必须非常清楚这个主题。

过去几周我一直在 运行 关注这个问题。我正在使用 flutter_bloc 包。

我有一个带有搜索框和列表视图的简单搜索页面 (ProposalSearchPage)。 Listview 基于派发 KeywordsearchEvent 的搜索关键字构建。单击设置图标打开 ProposalSearchSetting 页面,这是一个对话框页面。

基于这个结构,我在 bloc 中使用了两个事件。一个用于关键字搜索,另一个用于高级过滤器搜索。

应用过滤器后提前搜索页面。在一个按钮内,我发送了 FilterSearchEvent 并使用 Navigation.pop(context) 到 return 到 ProposalSearchPage。 基于状态变化,列表视图为这两个搜索呈现,但对于 Adavance 过滤器搜索,ProposalSearchSetting 对话框是部分可见的。那里的过滤器按钮是可点击的。当我点击后退按钮时它消失了。

我不知道为什么 Navigator.pop 将页面添加到堆栈而不是弹出堆栈。

  #PROPOSALSEARCH PAGE

class ProposalSearchPage extends StatefulWidget {
 final UserProfileBloc userProfileBloc;
 final MenuBloc menuBloc;
final String authToken;

  ProposalSearchPage({this.userProfileBloc, this.menuBloc, this.authToken})
  : assert(menuBloc != null),
    assert(userProfileBloc != null);

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

class _ProposalSearchPageState extends State<ProposalSearchPage> {
 UserProfileBloc get _userProfileBloc => widget.userProfileBloc;
 List filteredProposal = [];

String get _authToken => widget.authToken;

 MenuBloc get _menuBloc => widget.menuBloc;
ProposalSearchBloc _proposalSearchBloc;
String searchedKeyword = "";
int searchProposalPage = 1;

@override
void initState() {
_proposalSearchBloc =
    ProposalSearchBloc(proposalRepository: ProposalListingRepo());
_menuBloc.dispatch(MenuResponseFetchedEvent());
 super.initState();
}

@override
 void dispose() {
_proposalSearchBloc.dispose();
super.dispose();
  }

@override
Widget build(BuildContext context) {
 return Scaffold(
  appBar: AppBar(
    backgroundColor: Color(0xff2b57ff),
    leading: IconButton(
      icon: Icon(Icons.chevron_left),
      onPressed: () {
        Navigator.of(context).pop();
      },
    ),
    actions: <Widget>[
      IconButton(
          icon: new Icon(CupertinoIcons.gear_big),
          onPressed: () {
          /*  Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => ProposalSearchSetting(
                    proposalSearchBloc: _proposalSearchBloc,
                    menuBloc: _menuBloc,
                    userProfileBloc: _userProfileBloc,
                    context: context),
                fullscreenDialog: true,
              ),
            );*/

              showDialog<FilterProposalPost>(
                  context: context,
                  builder: (context) {
                    return ProposalSearchSetting(
                        proposalSearchBloc: _proposalSearchBloc,
                        menuBloc: _menuBloc,
                        userProfileBloc: _userProfileBloc,
                        context: context);
                  });
          }),
    ],
    title: Center(
      child: Container(
        width: 250.0,
        height: 35.0,
        decoration: BoxDecoration(
            color: Colors.black12,
            borderRadius: BorderRadius.all(Radius.circular(7.0))),
        child: CupertinoTextField(
          placeholder: 'search here.',
          style: TextStyle(
            color: Colors.white,
          ),
          onSubmitted: (keyword) {
            print(keyword);
            searchedKeyword = keyword;
            FilterProposalPost filterProposalPost =
                _buildSearchQueryParameter(keyword);
            // print(query);
            _proposalSearchBloc.proposalFilterPostParam(filterProposalPost);
          },
        ),
      ),
    ),
  ),
  body: SearchListing(_proposalSearchBloc, _authToken),
);
}

  FilterProposalPost _buildSearchQueryParameter(String keyword) {
  return FilterProposalPost(
  ........
   );
  }


  }


   }

 class SearchListing extends StatelessWidget {
 final ProposalSearchBloc _proposalSearchBloc;
 final String _authToken;

 SearchListing(this._proposalSearchBloc, this._authToken);

 @override
Widget build(BuildContext context) {
return BlocBuilder(
  bloc: _proposalSearchBloc,
  // ignore: missing_return
  builder: (context, state) {
    if (state is ProposalSearchFetchingState) {
      return Center(
        child: CircularProgressIndicator(
            valueColor: new AlwaysStoppedAnimation(Color(0xff2b57ff))),
      );
    } else if (state is ProposalSearchFetchedState) {
      final filteredProposal = state.filteredProposal;
      print(filteredProposal.length.toString);
      return _buildSearchProposalList(filteredProposal);
    }
  },
);
}

 Widget _buildSearchProposalList(List searchedProposals) {
return ListView.builder(
    itemCount: searchedProposals.length + 1,
    itemBuilder: (context, position) {
      return position >= searchedProposals.length
          ? _buildLoaderListItem()
          : ProposalCardFactory(
              proposal: searchedProposals[position],
              authToken: _authToken,
            );
    });
}

Widget _buildLoaderListItem() {
return Center(
    child: CircularProgressIndicator(
        valueColor: new AlwaysStoppedAnimation(Color(0xff2b57ff))));
 }
   }






#ProposalSearchSettingPage

class ProposalSearchSetting extends StatefulWidget {
final UserProfileBloc userProfileBloc;
final ProposalSearchBloc proposalSearchBloc;
final MenuBloc menuBloc;
final BuildContext context;

final Function() notifyParent;

 ProposalSearchSetting({this.notifyParent,
  this.proposalSearchBloc,
  this.userProfileBloc,
  this.menuBloc,
  this.context});

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

  class _ProposalSearchSettingState extends State<ProposalSearchSetting>
  with SingleTickerProviderStateMixin {
  UserProfileBloc get _userProfileBloc => widget.userProfileBloc;

   ProposalSearchBloc get _proposalSearchBloc => widget.proposalSearchBloc;
   List<String> selectedOptions = [];
  String resultBy;

List<String> industries;
List<String> stages;
 List<String> locations;
List<String> languages;
List<String> countries;
List<String> regionsValue = [];

 MenuBloc get _menuBloc => widget.menuBloc;
 Animation<double> animation;
 AnimationController controller;
 double startingPoint;

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

@override
void dispose() {
_userProfileBloc.dispose();
 _proposalSearchBloc.dispose();
 super.dispose();
 }

 @override
 Widget build(BuildContext context) {
 //double startingPoint = MediaQuery.of(context).size.height;
 return MaterialApp(
  theme: ThemeData(
      buttonTheme: ButtonThemeData(
          minWidth: 200.0,
          height: 40.0,
          buttonColor: Color(0xff2b57ff),
          textTheme: ButtonTextTheme.primary)),
  home: Scaffold(
    body: BlocBuilder(
      bloc: _menuBloc,
      // ignore: missing_return
      builder: (context, state) {
        if (state is MenuResponseFetchedState) {
          MenuListData _menuListData = state.menuListData;
          return Padding(
            padding: const EdgeInsets.only(top: 100.0),
            child: Center(
              child: Container(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    RaisedButton(
                      onPressed: () async {
                        resultBy = await showDialog(
                            context: context,
                            builder: (context) {
                              return ResultBySearchDialog(
                                  userProfileBloc: _userProfileBloc,
                                  menuListData: _menuListData,
                                  title: 'Result By:',
                                  options: _menuListData.displayBy.values
                                      .toList());
                            });
                      },
                      color: Color(0xff2b57ff),
                      child: Text(
                        'RESULT BY',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    RaisedButton(
                      onPressed: () async {
                        countries = await showDialog(
                            context: context,
                            builder: (context) {
                              return CountrySearchDialog(
                                  userProfileBloc: _userProfileBloc,
                                  menuListData: _menuListData,
                                  title: 'Select Countries',
                                  selectedOptions: selectedOptions,
                                  onSelectedOptionListChanged: (options) {
                                    selectedOptions = options;
                                    print(selectedOptions);
                                  });
                            });
                      },
                      color: Color(0xff2b57ff),
                      child: Text(
                        'COUNTRY',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    RaisedButton(
                      onPressed: () async {
                        industries = await showDialog(
                            context: context,
                            builder: (context) {
                              return IndustrySearchDialog(
                                  menuListData: _menuListData,
                                  title: 'Select Industries',
                                  options: _menuListData.industries.values
                                      .toList(),
                                  selectedOptions: selectedOptions,
                                  onSelectedOptionListChanged: (options) {
                                    selectedOptions = options;
                                    print(selectedOptions);
                                  });
                            });
                      },
                      child: Text(
                        'INDUSTRIES',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    RaisedButton(
                      onPressed: () async {
                        stages = await showDialog(
                            context: context,
                            builder: (context) {
                              return StageSearchDialog(
                                context: context,
                                  menuListData: _menuListData,
                                  title: 'Select Stages',
                                  options:
                                  _menuListData.stages.values.toList(),
                                  selectedOptions: selectedOptions,
                                  onSelectedOptionListChanged: (options) {
                                    selectedOptions = options;
                                    print(selectedOptions);
                                  });
                            });
                      },
                      child: Text(
                        'STAGES',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    RaisedButton(
                      onPressed: () async {
                        languages = await showDialog(
                            context: context,
                            builder: (context) {
                              return LanguageSearchDialog(
                                  menuListData: _menuListData,
                                  title: 'Select Languages',
                                  options: _menuListData.languages.values
                                      .toList(),
                                  selectedOptions: selectedOptions,
                                  onSelectedOptionListChanged: (options) {
                                    selectedOptions = options;
                                    print(selectedOptions);
                                  });
                            });
                      },
                      child: Text(
                        'LANGUAGES',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    RaisedButton(
                      onPressed: () async {
                        locations = await showDialog(
                            context: context,
                            builder: (context) {
                              return LocationSearchDialog(
                                  menuListData: _menuListData,
                                  title: 'Select Locations',
                                  options: _menuListData.locations.values
                                      .toList(),
                                  selectedOptions: selectedOptions,
                                  onSelectedOptionListChanged: (options) {
                                    selectedOptions = options;
                                    print(selectedOptions);
                                  });
                            });
                      },
                      child: Text(
                        'LOCATIONS',
                        style: TextStyle(fontFamily: 'MyRaidPro'),
                      ),
                    ),
                    SizedBox(
                      height: 40,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        ButtonTheme(
                          textTheme: ButtonTextTheme.primary,
                          minWidth: 60,
                          child: RaisedButton(
                            onPressed: () {
                              Navigator.of(this.widget.context).pop();
                            },
                            color: Color(0xff2b57ff),
                            child: Text(
                              'Cancel',
                              style: TextStyle(fontFamily: 'MyRaidPro'),
                            ),
                          ),
                        ),
                        ButtonTheme(
                          textTheme: ButtonTextTheme.primary,
                          minWidth: 60,
                          child: RaisedButton(
                            onPressed: () {


_proposalSearchBloc.dispatch(ProposalFilterFetchEvent(advanceFilter: 
 FilterProposalPost(......)));
                              Navigator.pop(context);

                              print(("value from dialog" +
                                  industries.toString()));

                              print(("value from dialog" +
                                  stages.toString()));

                              print(("value from dialog" +
                                  locations.toString()));

                              print(("value from dialog" +
                                  languages.toString()));
                            },
                            color: Color(0xff2b57ff),
                            child: Text(
                              'Apply',
                              style: TextStyle(fontFamily: 'MyRaidPro'),
                            ),
                          ),
                        )
                      ],
                    )
                  ],
                ),
              ),
            ),
          );
        }
      },
    ),
  ),
);
}

}

#BLOC



class ProposalSearchBloc
extends Bloc<ProposalSearchEvent, ProposalSearchState> {
  final ProposalListingRepo proposalRepository;
List keywordSearchedProposalList = List();
List filteredProposalList = List();

ProposalSearchBloc({this.proposalRepository});

 void proposalFilterPostParam(FilterProposalPost filterProposalPost) {
 dispatch(ProposalSearchFetchEvent(filterProposalPost: filterProposalPost));
 }



  @override
  ProposalSearchState get initialState => ProposalSearchFetchingState();

 @override
 Stream<ProposalSearchState> mapEventToState(event) async* {
try {
  var filteredProposal;
  print("proposal search even fired first time");
  if (event is ProposalSearchFetchEvent) {
    filteredProposal =
        await proposalRepository.filterProposal(event.filterProposalPost);
  } else if (event is ProposalFilterFetchEvent) {
    print("filter event");

    filteredProposal =
        await proposalRepository.filterProposal(event.advanceFilter);
    filteredProposalList.addAll(filteredProposal);
    yield ProposalSearchFetchedState(filteredProposal: filteredProposal);
  }
 } catch (_) {
  //print(error.toString());
  yield ProposalSearchErrorState();
 }
 }
}

终于解决了问题。我只是忘了在我的集团中使用 try catch blok。这解决了从另一个页面(可能是 DialogBox Box)更改配置后重新加载前一个页面的大部分问题。我只需要在 Bloc 代码中做一些更改:

 @override
  Stream<ProposalSearchState> mapEventToState(event) async* {
    yield ProposalSearchFetchingState();
  if (event is ProposalSearchFetchEvent) {
   try {
    print("proposal search");
    filteredProposal =
        await proposalRepository.filterProposal(event.filterProposalPost);

    yield ProposalSearchFetchedState(
        searchedProposal: filteredProposal);
  } catch (error) {
    print(error);
  }

  if (event is ProposalFilterFetchEvent) {
    try {
      print("proposal filtered");
      filteredProposal =
          await proposalRepository.filterProposal(event.filterProposalPost);

      yield ProposalFilteredFetchedState(
          filteredProposal: filteredProposal);
    } catch (error) {
      print(error.toString());
    }
  }
}

}