Flutter 将搜索数据传递给 SearchDelegate

Posted

技术标签:

【中文标题】Flutter 将搜索数据传递给 SearchDelegate【英文标题】:Flutter pass search data to SearchDelegate 【发布时间】:2019-12-12 12:46:23 【问题描述】:

我创建了带有标签的产品,所以当用户按下标签按钮时,它将打开 SearchDelegate 并搜索该标签,

那么如何将标签名称传递给搜索代理查询

我的代码:

class DataSearch extends SearchDelegate<Product> 
  final suggestions = new ProductsRepository().fetchAllProducts();
  final lastOnes = ['suggest'];

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

  @override
  Widget buildLeading(BuildContext context) 
    return IconButton(
        icon: AnimatedIcon(
          icon: AnimatedIcons.menu_arrow,
          progress: transitionAnimation,
        ),
        onPressed: () 
          close(context, null);
        );
  

  @override
  Widget buildResults(BuildContext context) 
    final suggestionList = query.isEmpty
        ? []
        : suggestions.where((p) => p.title.contains(query)).toList();
    double _gridSize =
        MediaQuery.of(context).size.height * 0.58; //88% of screen
    double childAspectRatio = MediaQuery.of(context).size.width /
        (MediaQuery.of(context).size.height / 1.0);

    return Column(children: <Widget>[
      new Container(
          height: _gridSize + 100,
          decoration: BoxDecoration(
            color: const Color(0xFFeeeeee),),
          padding: EdgeInsets.only(left: 10, right: 10),
          child: new Column(children: <Widget>[
            new Container(
                margin: EdgeInsets.only(top: 40),
                child: new Column(children: <Widget>[
                  new Container(
                      height: _gridSize - 60,
                      margin: EdgeInsets.only(top: 0),
                      child: new PhysicalModel(
                          color: Colors.transparent,
                          borderRadius: BorderRadius.only(
                              bottomLeft: Radius.circular(_gridSize / 10 - 10),
                              bottomRight:
                              Radius.circular(_gridSize / 10 - 10)),
                          clipBehavior: Clip.antiAlias,
                          child: GridView.builder(
                              itemCount: suggestionList.length,
                              gridDelegate:
                              new SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: 2,
                                  childAspectRatio: childAspectRatio),
                              itemBuilder: (BuildContext context, int index) 
                                return new Padding(
                                    padding: EdgeInsets.only(
                                        top: index % 2 == 0 ? 20 : 0,
                                        right: index % 2 == 0 ? 5 : 0,
                                        left: index % 2 == 1 ? 5 : 0,
                                        bottom: index % 2 == 1 ? 20 : 0),
                                    child:
                                    ProductWidget(
                                        product: suggestionList[index]));
                              )

                      )),

                ]))
          ])),
//      new MinimalCart(_gridSize)
    ]);
  

  @override
  Widget buildSuggestions(BuildContext context) 
    final suggestionList = query.isEmpty
        ? []
        : suggestions.where((p) => p.title.contains(query)).toList();
    return ListView.builder(
      itemBuilder: (context, index) =>
          ListTile(
            leading: Icon(Icons.add),
            onTap: () => showResults(context),
            title: RichText(
                text: TextSpan(
                    text: suggestionList[index].title.substring(
                        0, query.length),
                    style: TextStyle(
                        color: Colors.black, fontWeight: FontWeight.bold),
                    children: [
                      TextSpan(
                          text: suggestionList[index].title.substring(
                              query.length),
                          style: TextStyle(
                              color: Colors.grey))
                    ])),
          ),
      itemCount: suggestionList.length,
    );
  

我的标签按钮:

 child: FlatButton(
     child: Text(widget.product.tags[index]),
     onPressed: () 
            showSearch(
              context: context,
              delegate: DataSearch(),
         );

       )

我尝试传递 query 变量,但它不起作用,因为 query 在小部件内,有其他方法吗?

【问题讨论】:

【参考方案1】:

您可以使用参数q 作为String 和final 的DataSearch 的构造函数。然后将this.q 设置为您想要的查询。并在按钮中初始化DataSearch,并将产品标签作为参数。

试试这个代码,告诉我它是否有效。

class DataSearch extends SearchDelegate<Product> 
  final suggestions = new ProductsRepository().fetchAllProducts();
  final lastOnes = ['suggest'];

  final String q;

  DataSearch(this.q) 
       query = this.q;
  

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

  @override
  Widget buildLeading(BuildContext context) 
    return IconButton(
        icon: AnimatedIcon(
          icon: AnimatedIcons.menu_arrow,
          progress: transitionAnimation,
        ),
        onPressed: () 
          close(context, null);
        );
  

  @override
  Widget buildResults(BuildContext context) 
    final suggestionList = query.isEmpty
        ? []
        : suggestions.where((p) => p.title.contains(query)).toList();
    double _gridSize =
        MediaQuery.of(context).size.height * 0.58; //88% of screen
    double childAspectRatio = MediaQuery.of(context).size.width /
        (MediaQuery.of(context).size.height / 1.0);

    return Column(children: <Widget>[
      new Container(
          height: _gridSize + 100,
          decoration: BoxDecoration(
            color: const Color(0xFFeeeeee),),
          padding: EdgeInsets.only(left: 10, right: 10),
          child: new Column(children: <Widget>[
            new Container(
                margin: EdgeInsets.only(top: 40),
                child: new Column(children: <Widget>[
                  new Container(
                      height: _gridSize - 60,
                      margin: EdgeInsets.only(top: 0),
                      child: new PhysicalModel(
                          color: Colors.transparent,
                          borderRadius: BorderRadius.only(
                              bottomLeft: Radius.circular(_gridSize / 10 - 10),
                              bottomRight:
                              Radius.circular(_gridSize / 10 - 10)),
                          clipBehavior: Clip.antiAlias,
                          child: GridView.builder(
                              itemCount: suggestionList.length,
                              gridDelegate:
                              new SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: 2,
                                  childAspectRatio: childAspectRatio),
                              itemBuilder: (BuildContext context, int index) 
                                return new Padding(
                                    padding: EdgeInsets.only(
                                        top: index % 2 == 0 ? 20 : 0,
                                        right: index % 2 == 0 ? 5 : 0,
                                        left: index % 2 == 1 ? 5 : 0,
                                        bottom: index % 2 == 1 ? 20 : 0),
                                    child:
                                    ProductWidget(
                                        product: suggestionList[index]));
                              )

                      )),

                ]))
          ])),
//      new MinimalCart(_gridSize)
    ]);
  

  @override
  Widget buildSuggestions(BuildContext context) 
    final suggestionList = query.isEmpty
        ? []
        : suggestions.where((p) => p.title.contains(query)).toList();
    return ListView.builder(
      itemBuilder: (context, index) =>
          ListTile(
            leading: Icon(Icons.add),
            onTap: () => showResults(context),
            title: RichText(
                text: TextSpan(
                    text: suggestionList[index].title.substring(
                        0, query.length),
                    style: TextStyle(
                        color: Colors.black, fontWeight: FontWeight.bold),
                    children: [
                      TextSpan(
                          text: suggestionList[index].title.substring(
                              query.length),
                          style: TextStyle(
                              color: Colors.grey))
                    ])),
          ),
      itemCount: suggestionList.length,
    );
  

还有你的按钮

child: FlatButton(
     child: Text(widget.product.tags[index]),
     onPressed: () 
            showSearch(
              context: context,
              delegate: DataSearch(widget.product.tags[index]),
         );

       )

【讨论】:

idk 为什么我无法弄清楚这一点,感谢@Shady Boshra。这对我有用

以上是关于Flutter 将搜索数据传递给 SearchDelegate的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中,如何将数据传递给 Stateless Widget?

如何将非字符串数据传递给 Flutter 中的命名路由?

Flutter(Web)如何监听javascript事件或将javascript数据传递给flutter?

将 StatefulWidget 数据传递给 State 类而不使用构造函数

制作某种具有多行的行构建器并将 JSON 数据传递给其中的最佳方法是啥。扑

SwiftUI 如何将数据传递给 ObservedObject 函数