简体   繁体   English

如何实现 Flutter 搜索应用栏

[英]How to implement a Flutter Search App Bar

There are a lot of tutorials but rather than help me to move forward, I get lost in all possible options or I don't know how to improve the code (I would like to use an application that displays a list that use more than only the name of three fruits or three cities?)有很多教程,但不是帮助我前进,而是迷失在所有可能的选项中,或者我不知道如何改进代码(我想使用一个显示列表的应用程序,该列表不仅使用三个水果的名字还是三个城市的名字?)

I found tutorials to create a nice SearchBar with the ability to display the result based on the first letters typed.我找到了创建一个很好的 SearchBar 的教程,它能够根据输入的第一个字母显示结果。

I don't understand how to edit the tutorial with a data list that includes a title associated with the content.我不明白如何使用包含与内容关联的标题的数据列表来编辑教程。 I don't understand how to display the result if the first letter is lowercase or uppercase.如果第一个字母是小写或大写,我不明白如何显示结果。 Would it be possible to help me to make a simple basic code that could serve everyone including beginners like me?是否有可能帮助我制作一个简单的基本代码,可以为所有人服务,包括像我这样的初学者?

DataList.dart数据列表.dart

List<ListWords>  listWords = [
  ListWords('oneWord', 'OneWord definition'),
  ListWords('twoWord', 'TwoWord definition.'),
  ListWords('TreeWord', 'TreeWord definition'),
];

class ListWords {
  String titlelist;
  String definitionlist;

  ListWords(String titlelist, String definitionlist) {
    this.titlelist = titlelist;
    this.definitionlist = definitionlist;
  }
}

Searchbar.dart搜索栏.dart

import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';

class SearchBar extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Search App'),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.search),
              onPressed: () {
                showSearch(context: context, delegate: DataSearch(listWords));
              })
        ],
      ),
      drawer: Drawer(),
    );
  }
}

class DataSearch extends SearchDelegate<String> {

  final List<ListWords> listWords;

  DataSearch(this.listWords);


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

  @override
  Widget buildLeading(BuildContext context) {
    //leading icon on the left of the app bar
    return IconButton(
        icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
          progress: transitionAnimation,
        ),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    // show some result based on the selection
    return Center(
      child: Text(query),

    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    // show when someone searches for something
    final suggestionList = query.isEmpty
        ? listWords
        : listWords.where((p) => p.startsWith(query)).toList();



    return ListView.builder(itemBuilder: (context, index) => ListTile(
      onTap: () {
        showResults(context);
      },
      trailing: Icon(Icons.remove_red_eye),
      title: RichText(
        text: TextSpan(
            text: suggestionList[index].titlelist.substring(0, query.length),
            style: TextStyle(
                color: Colors.red, fontWeight: FontWeight.bold),
            children: [
              TextSpan(
                  text: suggestionList[index].titlelist.substring(query.length),
                  style: TextStyle(color: Colors.grey))
            ]),
      ),
    ),
      itemCount: suggestionList.length,
    );
  }
}

To create a search appbar, you will need a stateful widget with the following code,要创建搜索应用栏,您将需要一个带有以下代码的有状态小部件,

Inside your State class,在您的 State class 内部,

  TextEditingController _searchQueryController = TextEditingController();
  bool _isSearching = false;
  String searchQuery = "Search query";

Inside Scaffold, your appbar should be like,在 Scaffold 里面,你的 appbar 应该是这样的,

appBar: AppBar(
        leading: _isSearching ? const BackButton() : Container(),
        title: _isSearching ? _buildSearchField() : _buildTitle(context),
        actions: _buildActions(),
      ),

Define the required following methods for displaying and managing searchbar,定义显示和管理搜索栏所需的以下方法,

Widget _buildSearchField() {
    return TextField(
      controller: _searchQueryController,
      autofocus: true,
      decoration: InputDecoration(
        hintText: "Search Data...",
        border: InputBorder.none,
        hintStyle: TextStyle(color: Colors.white30),
      ),
      style: TextStyle(color: Colors.white, fontSize: 16.0),
      onChanged: (query) => updateSearchQuery(query),
    );
  }

  List<Widget> _buildActions() {
    if (_isSearching) {
      return <Widget>[
        IconButton(
          icon: const Icon(Icons.clear),
          onPressed: () {
            if (_searchQueryController == null ||
                _searchQueryController.text.isEmpty) {
              Navigator.pop(context);
              return;
            }
            _clearSearchQuery();
          },
        ),
      ];
    }

    return <Widget>[
      IconButton(
        icon: const Icon(Icons.search),
        onPressed: _startSearch,
      ),
    ];
  }

  void _startSearch() {
    ModalRoute.of(context)
        .addLocalHistoryEntry(LocalHistoryEntry(onRemove: _stopSearching));

    setState(() {
      _isSearching = true;
    });
  }

  void updateSearchQuery(String newQuery) {
    setState(() {
      searchQuery = newQuery;
    });
  }

  void _stopSearching() {
    _clearSearchQuery();

    setState(() {
      _isSearching = false;
    });
  }

  void _clearSearchQuery() {
    setState(() {
      _searchQueryController.clear();
      updateSearchQuery("");
    });
  }

This is the best way to implement an app searchbar in any flutter screen.这是在任何 flutter 屏幕中实现应用程序搜索栏的最佳方式。

Finally, I managed to do this.最后,我设法做到了。 This is a good starting point for the Search Show in a list.这是在列表中搜索显示的一个很好的起点。 Does this are correct?这是正确的吗?

DataList.dart数据列表.dart

List<ListWords>  listWords = [
  ListWords('oneWord', 'OneWord definition'),
  ListWords('twoWord', 'TwoWord definition.'),
  ListWords('TreeWord', 'TreeWord definition'),
];

class ListWords {
  String titlelist;
  String definitionlist;

  ListWords(String titlelist, String definitionlist) {
    this.titlelist = titlelist;
    this.definitionlist = definitionlist;
  }
}

SearchBar.dart搜索栏.dart

import 'dart:core';
import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';
import 'package:test_searchbar/detail.dart';

class SearchBar extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Search App'),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.search),
              onPressed: () {
                showSearch(context: context, delegate: DataSearch(listWords));
              })
        ],
      ),
      body: Center(
          child: Text('default content')
      ),
      drawer: Drawer(),
    );
  }
}

class DataSearch extends SearchDelegate<String> {

  final List<ListWords> listWords;

  DataSearch(this.listWords);

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

  @override
  Widget buildLeading(BuildContext context) {
    //leading icon on the left of the app bar
    return IconButton(
        icon: AnimatedIcon(icon: AnimatedIcons.menu_arrow,
          progress: transitionAnimation,
        ),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    // show some result based on the selection
    final suggestionList = listWords;

    return ListView.builder(itemBuilder: (context, index) => ListTile(

      title: Text(listWords[index].titlelist),
      subtitle: Text(listWords[index].definitionlist),
    ),
      itemCount: suggestionList.length,
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    // show when someone searches for something

    final suggestionList = query.isEmpty
        ? listWords
        : listWords.where((p) => p.titlelist.contains(RegExp(query, caseSensitive: false))).toList();


    return ListView.builder(itemBuilder: (context, index) => ListTile(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => Detail(listWordsDetail: suggestionList[index]),
          ),
        );
      },
      trailing: Icon(Icons.remove_red_eye),
      title: RichText(
        text: TextSpan(
            text: suggestionList[index].titlelist.substring(0, query.length),
            style: TextStyle(
                color: Colors.red, fontWeight: FontWeight.bold),
            children: [
              TextSpan(
                  text: suggestionList[index].titlelist.substring(query.length),
                  style: TextStyle(color: Colors.grey)),
            ]),
      ),
    ),
      itemCount: suggestionList.length,
    );
  }
}

detail.dart详情.dart

import 'package:flutter/material.dart';
import 'package:test_searchbar/DataList.dart';

class Detail extends StatelessWidget {

  final ListWords listWordsDetail;

  Detail({Key key, @required this.listWordsDetail}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          brightness: Brightness.dark,
          title: const Text('Détail', style: TextStyle(color: Colors.white)),
          iconTheme: IconThemeData(color: Colors.white),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(listWordsDetail.titlelist +' (on detail page)'),
              Text(listWordsDetail.definitionlist),
            ],
          ),
        )
    );
  }
}

It would be best if the return from the detail page opens the Searchbar page with the default content and the closed searchbar...最好是从详细页面返回打开带有默认内容的搜索栏页面和关闭的搜索栏...

Thank you for responding quickly.感谢您快速回复。

As Tinus Jackson said, is not the use of show search the best way to use the Flutter method?正如Tinus Jackson所说,使用show search是不是最好使用Flutter方法?

Is it not possible from show search to use a complex list from a data file?从显示搜索中是否不可能使用数据文件中的复杂列表?

Same for displaying the first letter, etc. this is not possible with show search?与显示第一个字母等相同。这在显示搜索中是不可能的吗?

Thank you for your time, I test all that and come back maybe with other questions...谢谢你的时间,我测试了所有这些,然后可能会带着其他问题回来......

Scaffold(
        appBar: AppBar(
          backgroundColor: Color.fromRGBO(93, 25, 72, 1),
          toolbarHeight: 60.0,
          title: TextField(
            cursorColor: Colors.white,
            decoration: InputDecoration(
                hintText: " Search...",
                border: InputBorder.none,
                suffixIcon: IconButton(
                  icon: Icon(Icons.search),
                  color: Color.fromRGBO(93, 25, 72, 1),
                  onPressed: () {},
                )),
            style: TextStyle(color: Colors.white, fontSize: 15.0),
          ),
        ),
);

There is a ready to use widget for this:有一个现成的小部件用于此:

      appBar: AppBarWithSearchSwitch(
        onChanged: (text) {
          searchText.value = text;
        }, // or use: onSubmitted: (text) => searchText.value = text,
        appBarBuilder: (context) {
          return AppBar(
            title: Text('Example '),
            actions: [
              AppBarSearchButton(), // button to activate search
            ],

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM