【问题标题】:how to make flutter searchDelagate a separate screen that can be navigated to independently?如何让flutter searchDelagate成为一个可以独立导航到的独立屏幕?
【发布时间】:2021-02-10 06:53:22
【问题描述】:

我有一个名为 searchUsersScreen 的页面,它是这样的:

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:myApp/models/otherUser.dart';
import 'package:myApp/ui/widgets/user_profile.dart';

import 'database.dart';

class SearchUsersScreen extends StatefulWidget {
  @override
  _SearchUsersScreenState createState() => _SearchUsersScreenState();
}

class _SearchUsersScreenState extends State<SearchUsersScreen> {
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => showSearch(
          context: context,
          delegate: SearchUsers(
            DatabaseService().fetchUsersInSearch(),
          ),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Theme.of(context).primaryColor,
    );
  }
}

在同一个 dart 文件中有这个 searchDelegate :


//Search delegate
class SearchUsers extends SearchDelegate<OtherUser> {
  final Stream<QuerySnapshot> otherUser;
  final String hashtagSymbol = 'assets/svgs/flaticon/hashtag_symbol.svg';

  SearchUsers(this.otherUser);
  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
        icon: Icon(Icons.clear),
        onPressed: () {
          query = '';
        },
      ),
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return Container(
      width: 0,
      height: 0,
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    return Container(
      width: 0,
      height: 0,
      color: Theme.of(context).primaryColor,
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    showUserProfile(String userId) {
      Navigator.push(
          context,
          MaterialPageRoute(
              builder: (context) => UserProfileView(
                    userUid: userId,
                  )));
    }

    return StreamBuilder<QuerySnapshot>(
        stream: DatabaseService().fetchUsersInSearch(),
        builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {

          final handlesResults = snapshot.data.documents
              .where((u) => u['username'].contains(query));

          if (!snapshot.hasData) {
            return Container(
              color: Theme.of(context).primaryColor,
              child: Center(
                child: Text(
                  '',
                  style: TextStyle(
                      fontSize: 16, color: Theme.of(context).primaryColor),
                ),
              ),
            );
          }
          if (handlesResults.length > 0) {
            return Container(
              color: Theme.of(context).primaryColor,
              child: ListView(
                children: handlesResults
                    .map<Widget>((u) => GestureDetector(
                          child: Padding(
                            padding: const EdgeInsets.all(0.1),
                            child: Container(
                              padding: EdgeInsets.symmetric(vertical: 5),
                              decoration: BoxDecoration(
                                  color: Theme.of(context).primaryColor,
                                  border: Border(
                                      bottom: BorderSide(
                                          width: 0.3, color: Colors.grey[50]))),
                              child: ListTile(
                                leading: CircleAvatar(
                                        backgroundColor:
                                            Theme.of(context).primaryColor,
                                        backgroundImage:
                                            NetworkImage(u['userAvatarUrl']),
                                        radius: 20,
                                      ),
                                title: Container(
                                  padding: EdgeInsets.only(left: 10),
                                  child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: [
                                      Text(u['username'],
                                          style: TextStyle(
                                              fontSize: 16,
                                              color: Theme.of(context)
                                                  .accentColor),
                                          overflow: TextOverflow.ellipsis),
                                      SizedBox(
                                        height: 5,
                                      ),
                                       Text(u['name'],
                                              style: TextStyle(
                                                fontSize: 16,
                                                color: Colors.grey[500],
                                              ),
                                              overflow: TextOverflow.ellipsis),
                                    ],
                                  ),
                                ),
                                trailing: Container(
                                  padding: EdgeInsets.only(left: 10),
                                  height: 43.0,
                                  width: MediaQuery.of(context).size.width / 2,
                                
                                ),
                              ),
                            ),
                          ),
                          onTap: () {
                            showUserProfile(u['id']);
                          },
                        ))
                    .toList(),
              ),
            );
          } else {
            return Container(
              color: Theme.of(context).primaryColor,
              child: Center(
                child: Text(
                  'No results found',
                  style: TextStyle(
                    fontSize: 16,
                    color: Theme.of(context).accentColor,
                  ),
                ),
              ),
            );
          }
        });
  }
}

我想将 SearchUsers 类用作一个单独的屏幕,我可以独立导航到该屏幕...但由于 SearchUsers 不评估小部件,因此无法实现。

所以我构建了 SearchUsersScreen statefulWidget,在它里面是 initState() 我称之为:

  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => showSearch(
          context: context,
          delegate: SearchUsers(
            DatabaseService().fetchUsersInSearch(),
          ),
        ));
  }

当用户导航到 SearchUsersScreen 时自动启动搜索功能。

我最终遇到了两个问题:

  1. SearchUsers 全屏显示在 SearchUsersScreen 之上(我不希望这种行为),我希望它显示在其中。 实际上它覆盖了我为在屏幕之间导航而构建的 BottomNavigationBar。

  2. 在 SearchUsers 被显示(并且它的工作做得很好)之后,当我点击设备返回按钮时......我离开 SearchUsers 并返回 SearchUsersScreen......这确实是一个空白屏幕。


所以总结一下......我想要的只是使用 SearchUsers 类作为一个小部件,我可以独立导航到它并从中导航......就是这样。

任何帮助将不胜感激。

感谢您花时间阅读。

【问题讨论】:

  • 如果我理解正确,这个答案可以帮助您解决导航问题stackoverflow.com/a/66059394/10595176。长话短说,使用嵌套导航器。
  • 感谢您的回答...我学到了一些新东西 :) 让您知道...我创建了上述所有方法并遇到了问题,因为我没有找到解决方案我自己的问题也在这里......这是我这样做的主要原因stackoverflow.com/questions/66114606/…

标签: flutter dart


【解决方案1】:

与其尝试创建单独的小部件 SearchUsers,不如尝试创建一个对话框并在有人想要搜索用户时显示它。在这种情况下,您还可以使用导航器和后退按钮,并将参数从下一个屏幕传递到上一个屏幕。

【讨论】:

  • 是的可能是个好主意....使用 showSearch() 函数,我可以从我想要的任何地方触发 searchDelegate 类....但是这里的重点...是我想要searchDelegate 在我导航到特定页面时自动触发....我试图使 SearchDelegate 成为有状态或无状态的小部件,但我没有运气....所以我创建了一个单独的小部件并调用了搜索委托一旦用户导航到该页面,就会触发 int initState()
  • 为什么不使用 Provider for searchDelegate 并在要调用该函数的小部件中收听它。在 build 方法中收听它,每当您导航到它时,都会调用该函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
  • 1970-01-01
  • 2020-11-08
  • 2015-09-25
  • 1970-01-01
相关资源
最近更新 更多