【问题标题】:Using TabBar like filter使用类似 TabBar 的过滤器
【发布时间】:2021-07-05 11:51:44
【问题描述】:

我正在尝试在按下搜索图标时创建一个出现在新页面中的 Tabbar。代码工作正常,但我不知道如何实现这个标签栏。我想使用标签栏来拆分搜索信息,每个图标必须只显示特定信息。

我猜每个图标都有一个特定的列表?

这是我的 search_tool.dart 当按下主页上的图标按钮时出现

[EDIT] 现在结果显示正确,但是当我按下搜索框写入 buildSuggestion 中包含的错误消息时,总是出现,它应该只显示具有相关记录的列表和如果搜索到不属于该类别的内容,则它必须给出错误消息

import 'package:flutter/material.dart';
import 'package:solaris/lista_data.dart';
import 'constants.dart';

class LinkItemsSearch extends SearchDelegate<LinkItem>{
  @override
  PreferredSizeWidget buildBottom(BuildContext context) {

    return PreferredSize(
      child: Container(
        alignment: Alignment.center,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Apps';
                    this.showResults(context);
                  },
                  child: Text('Apps'),
                ),
              ),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Movies';
                    this.showResults(context);
                  },
                  child: Text('Movies'),
                ),
              ),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Games';
                    this.showResults(context);
                  },
                  child: Text('Games'),
                ),
              ),
            ],
          ),
        ),
      ),
      preferredSize: Size.fromHeight(60),
    );
  }

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

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back),);
  }

  @override
  Widget buildResults(BuildContext context) {

    var mylist = loadLinkItem().where((p) => p.description.contains(query)).toList();

    return Container(
      color: blue,
      child: ListView.builder(
          itemCount: mylist.length,
          itemBuilder: (context,index){
            final LinkItem listitem = mylist[index];
            return Container(
              color: blue,
              child: ListTile(
                title:InkWell(
                  onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget> [
                      Text(listitem.title, style: TextStyle(color: Colors.white),),
                      Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
                      Divider(color: white,),
                    ],
                  ),
                ),
              ),
            );
          }
      ),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {

        final mylist = query.isEmpty? loadLinkItem():loadLinkItem().where((p) => p.description.contains(RegExp(query, caseSensitive: false))).toList();

    return mylist.isEmpty?
    Container(
      color: red,
      child: Center(child: Text('No Result Found . . .', style: TextStyle(color: Colors.white,fontSize: 20,))),
    ):Container(
      color: blue,
      child: ListView.builder(
          itemCount: mylist.length,
          itemBuilder: (context,index){
            final LinkItem listitem = mylist[index];
            return Container(
              color: blue,
              child: ListTile(onTap: (){ showResults(context);},
                title:InkWell(
                  onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget> [
                      Text(listitem.title, style: TextStyle(color: Colors.white),),
                      Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
                      Divider(color: white,),
                    ],
                  ),
                ),
              ),
            );
          }
      ),
    );
  }

}

搜索图标

IconButton(onPressed:(){
   showSearch(context: context, delegate: LinkItemsSearch());
}, icon: Icon(Icons.search),),

列表

class LinkItem{
  final String title;
  final String description;
  final link;
  LinkItem({
    required this.title,
    required this.description,
    required this.link,
});
}

List<LinkItem> loadLinkItem(){
  var link = <LinkItem>[
    LinkItem(
        title: 'Title1',
        description: 'Apps',
        link: Title1(),
    ),LinkItem(
        title: 'Title2',
        description: 'Movies',
        link: Title2(),
    ),LinkItem(
        title: 'Title3',
        description: 'Games',
        link: Title3(),
    ),
  ];
  return link;
}

【问题讨论】:

  • 您可以覆盖buildBottom 方法,它是PreferredSizeWidget 的一种,但不确定这是否适用于您的情况。您能否提供更多细节或更好的 UI 外观,我可以提供帮助吗?
  • 当然,第一张是我得到的,第二张是我想要的。当我单击第一个按钮时,它必须只显示与该按钮相关的内容,而不是其他按钮的内容,反之亦然。另外我不知道如何将顶部的灰色部分更改为默认的蓝色。链接:imgur.com/a/z8GQ4v2
  • 好的,知道了。让我为您创建一个示例,我将提供它作为新答案。

标签: flutter dart flutter-layout


【解决方案1】:

您可以在LinkItemsSearch 中覆盖buildBottom 方法:

@override
PreferredSizeWidget buildBottom(BuildContext context) {
  return PreferredSize(
    child: Container(
      alignment: Alignment.center,
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: [
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 8),
              child: ElevatedButton(
                onPressed: () {
                  query = 'Apps';

                  mylist = loadLinkItem()
                      .where((p) => p.description.contains(query))
                      .toList();

                  this.showResults(context);
                },
                child: Text('Apps'),
              ),
            ),
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 8),
              child: ElevatedButton(
                onPressed: () {
                  query = 'Movies';

                  mylist = loadLinkItem()
                      .where((p) => p.description.contains(query))
                      .toList();

                  this.showResults(context);
                },
                child: Text('Movies'),
              ),
            ),
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 8),
              child: ElevatedButton(
                onPressed: () {
                  query = 'Games';

                  mylist = loadLinkItem()
                      .where((p) => p.description.contains(query))
                      .toList();

                  this.showResults(context);
                },
                child: Text('Games'),
              ),
            ),
          ],
        ),
      ),
    ),
    preferredSize: Size.fromHeight(60),
  );
}

为此,您必须在 LinkItemsSearch 的顶部创建 myList 并在到处过滤时重复使用它。 另外,我刚刚更新了loadLinkItem 方法以获取一些过滤输入:

List<LinkItem> loadLinkItem() {
  var link = <LinkItem>[
    LinkItem(
      title: 'Title1',
      description: 'Movies',
      link: '',
    ),
    LinkItem(
      title: 'Title2',
      description: 'Games',
      link: '',
    ),
    LinkItem(
      title: 'Title3',
      description: 'Apps',
      link: '',
    ),
  ];
  return link;
}

当然,我没有完全匹配你的风格,所以我没有按照你的需要来设计按钮,你可能会比我使用的 60 更高的底部栏。我也没有附加任何新闻处理程序,因为我不确定他们应该做什么,但它看起来符合预期:https://i.stack.imgur.com/osUkt.png

我用ColumnSingleChildScrollView 将它们包裹起来,以防您有更多这些项目并且它们需要可滚动:https://i.stack.imgur.com/FyWVX.png

您甚至可以在不需要显示此底栏的情况下添加一些条件,在这种情况下,您可以从buildBottom 方法中返回null

【讨论】:

  • 很好,不用担心样式,但我不明白单击特定按钮时如何显示内容。无论按下哪个按钮,代码现在总是显示 3 行,我该如何解决?
  • 例如,如果我按 App 只会出现列表 Title1、Title2 等,如果我按 Movies 则只会出现列表 Movies1、Movies2 等。
  • 我明白了,我会稍微更新一下我的答案以提供答案。
  • 应该和你现在需要的差不多吧?
  • 好的,知道了。我会努力解决的。
【解决方案2】:

修复

import 'package:flutter/material.dart';
import 'package:solaris/lista_data.dart';
import 'constants.dart';

class LinkItemsSearch extends SearchDelegate<LinkItem>{
  @override
  PreferredSizeWidget buildBottom(BuildContext context) {

    return PreferredSize(
      child: Container(
        alignment: Alignment.center,
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Apps';
                    this.showResults(context);
                  },
                  child: Text('Apps'),
                ),
              ),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Movies';
                    this.showResults(context);
                  },
                  child: Text('Movies'),
                ),
              ),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8),
                child: ElevatedButton(
                  onPressed: () {
                    query = 'Games';
                    this.showResults(context);
                  },
                  child: Text('Games'),
                ),
              ),
            ],
          ),
        ),
      ),
      preferredSize: Size.fromHeight(60),
    );
  }

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

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back),);
  }

  @override
  Widget buildResults(BuildContext context) {

    var mylist = loadLinkItem().where((p) => p.description.contains(query)).toList();

    return Container(
      color: blue,
      child: ListView.builder(
          itemCount: mylist.length,
          itemBuilder: (context,index){
            final LinkItem listitem = mylist[index];
            return Container(
              color: blue,
              child: ListTile(
                title:InkWell(
                  onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget> [
                      Text(listitem.title, style: TextStyle(color: Colors.white),),
                      Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
                      Divider(color: white,),
                    ],
                  ),
                ),
              ),
            );
          }
      ),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final mylist = query.isEmpty? loadLinkItem():loadLinkItem().where((p) => p.description.contains(RegExp(query, caseSensitive: false))).toList();
    return mylist.isEmpty?
    Container(
      color: red,
      child: Center(child: Text('No Result Found . . .', style: TextStyle(color: Colors.white,fontSize: 20,))),
    ):Container(
      color: blue,
      child: ListView.builder(
          itemCount: mylist.length,
          itemBuilder: (context,index){
            final LinkItem listitem = mylist[index];
            return Container(
              color: blue,
              child: ListTile(onTap: (){ showResults(context);},
                title:InkWell(
                  onTap: () { Navigator.pushReplacement(context,MaterialPageRoute(builder: (context) => listitem.link)); },
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget> [
                      Text(listitem.title, style: TextStyle(color: Colors.white),),
                      Text(listitem.description, style: TextStyle(color: Colors.white,fontSize: 14),),
                      Divider(color: white,),
                    ],
                  ),
                ),
              ),
            );
          }
      ),
    );
  }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多