Flutter之不简单的搜索条

使用Flutter开发搜索条的代码如下:

main.dart

import 'package:flutter/material.dart';
import 'search_bar.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '不简单的搜索条',
      theme: ThemeData.light(),
      home: SearchBar(),
    );
  }
}

class SearchBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('不简单的搜索条'),
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            onPressed: (){
              print('搜索按钮被点击了');
              showSearch(context: context, delegate: SeachBarDelegate());
            }
          )
        ],
      ),
    );
  }
}

assets.dart

const searchSuggestions = [
  '政治新闻',
  '娱乐新闻',
  '体育新闻',
  '技术知识'
];

const searchList = [
  'Flutter基础',
  'Flutter进阶',
  'Flutter实战',
  'JavaSE',
  'JavaEE'
];

search_bar.dart

import 'assets.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget buildResults(BuildContext context) {
    return Container(
      width: 100.0,
      height: 100.0,
      child: Card(
        child: Center(
          child: Text(query),
        ),
        color: Colors.redAccent,
      ),
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    List list = query.isEmpty ? searchSuggestions : searchList.where((txt) => txt.startsWith(query)).toList();
    return ListView.builder(
      itemCount: list.length,
      itemBuilder: (BuildContext cxt, int index){
        return ListTile(
          title: RichText(
            text: TextSpan(
              text:list[index].substring(0,query.length),
              style: TextStyle(
                color: Colors.black,
                fontWeight: FontWeight.bold
              ),
              children: [
                TextSpan(
                  text:list[index].substring(query.length),
                  style: TextStyle(
                    color: Colors.grey,
                  )
                )
              ]
            )
          )
        );
      },
    );
  }
}

效果如下:

 

 

 

 

 

 

 

 

 

 

 

编程要点如下:

1.使用

showSearch(context: context, delegate: SeachBarDelegate());

调用自定义的搜索页面。

2.自定义的搜索页面类SeachBarDelegate需要继承SearchDelegate<String>,并且重写4个方法。

3.query是内置的变量,即输入的搜索内容。用query=""可清空搜索内容。

4.AnimatedIcon是动画图标,用法与Icon差不多。progess可以设置成transitionAnimation。

点击返回上级页面,即

onPressed: ()=>close(context,null)

5.使用

List list = query.isEmpty ? searchSuggestions : searchList.where((txt) => txt.startsWith(query)).toList();

对query值判空,若为空则返回搜索建议列表,否则在搜索列表中使用where查询符合query开头的字符串并用toList函数生成列表。

6.使用ListView.builder生成List视图,ListView中每一项都是一个ListTile。

7.在ListTile使用富文本组件和单行文字组件显示效果各异的一行文字,使用TextSpan的children属性可以连续嵌套。

 

posted @ 2021-04-16 15:40  罗毅豪  阅读(318)  评论(0编辑  收藏  举报