flutter_weixin搜索高亮功能实现

1、定义模型数组,储存搜索数据

//搜索得到的数组
  List<String> models = [];

  //所有联系人数据
  List<String> allModels = [
    '刘备',
    '孙权',
    "诸葛亮",
    "赵云",
    "周瑜",
    "鲁肃",
    "司马懿",
    "袁绍",
    "华佗",
    "华雄",
    "公孙瓒",
    "刘表",
    "典韦",
    "黄忠",
    "刘禅",
    "徐庶",
    "郭嘉",
    "荀攸",
    '曹操',
  ];

2、模型数组添加数据

//输入的字符
  String words = '';
  //搜索展示的内容
  void searcherData(String text) {
    models.clear();
    words=text;
    if (text.isNotEmpty) {
      for (int i = 0; i < allModels.length; i++) {
        String name = allModels[i];
        if (name.contains(text)) {
          models.add(name);
        }
      }
    }
    setState(() {});
  }

使用contains函数,获取所有含有输出值text的姓名

3、拼接模型数据,实现高亮

//文本颜色
  final TextStyle _normalStyle = const TextStyle(
    fontSize: 16,
    color: Colors.black,
  );

  final TextStyle _heighlightStyle = const TextStyle(
    fontSize: 16,
    color: Colors.green,
  );


  Widget _title(String name){
    List<TextSpan> spans = [];
    List<String> strs = name.split(widget.words);
    for(int i = 0;i<strs.length;i++){
      String str = strs[i];
      if(str == '' && i<strs.length-1){
        spans.add(TextSpan(text:widget.words,style: _heighlightStyle));
      } else {
        spans.add(TextSpan(text: str, style: _normalStyle));
        if(i<strs.length-1){
          spans.add(TextSpan(text:widget.words,style: _heighlightStyle));
        }
      }
    }
    return RichText(text: TextSpan(children: spans));
  }

将输入值进行高亮,利用split实现。逻辑:每分割一个字符,必定会含有一个输入值,所有每次都会在其他分割字符后加上高亮输入值(最后一个分割字符除外);如果是一开始就被分割,第一个字符就是空,则直接添加高亮输入值。

效果展示:

完整代码:

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

import '../XKTabBar.dart';
import '../other/line.dart';

class SearcherPeople extends StatefulWidget {
  final String titlesList;
  final String words;
  const SearcherPeople(this.titlesList, this.words, {Key? key}) : super(key: key);


  @override
  State<SearcherPeople> createState() => _ContactPeopleState();
}

class _ContactPeopleState extends State<SearcherPeople> {
  //文本颜色
  final TextStyle _normalStyle = const TextStyle(
    fontSize: 16,
    color: Colors.black,
  );

  final TextStyle _heighlightStyle = const TextStyle(
    fontSize: 16,
    color: Colors.green,
  );


  Widget _title(String name){
    List<TextSpan> spans = [];
    List<String> strs = name.split(widget.words);
    for(int i = 0;i<strs.length;i++){
      String str = strs[i];
      if(str == '' && i<strs.length-1){
        spans.add(TextSpan(text:widget.words,style: _heighlightStyle));
      } else {
        spans.add(TextSpan(text: str, style: _normalStyle));
        if(i<strs.length-1){
          spans.add(TextSpan(text:widget.words,style: _heighlightStyle));
        }
      }
    }
    return RichText(text: TextSpan(children: spans));
  }



  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          height: 50.0,
          color: Colors.white,
          child: ListTile(
            title: _title(widget.titlesList),
            leading: Image.asset(
              "images/${widget.titlesList}.png",
              width: 35.0,
              height: 35.0,
              fit: BoxFit.cover,
            ),
          ),
        ),
        const line(),
      ],
    );
  }
}
//search_page.dart
import 'package:flutter/material.dart';
import 'package:weixin/widget/searcher_people.dart';

import 'Home.dart';


class SearcherBar extends StatefulWidget {
  const SearcherBar({super.key});

  @override
  State<SearcherBar> createState() => _SearcherBarState();
}

class _SearcherBarState extends State<SearcherBar> {
  final TextEditingController _controller = TextEditingController();

  //搜索得到的数组
  List<String> models = [];

  //所有联系人数据
  List<String> allModels = [
    '刘备',
    '孙权',
    "诸葛亮",
    "赵云",
    "周瑜",
    "鲁肃",
    "司马懿",
    "袁绍",
    "华佗",
    "华雄",
    "公孙瓒",
    "刘表",
    "典韦",
    "黄忠",
    "刘禅",
    "徐庶",
    "郭嘉",
    "荀攸",
    '曹操',
  ];
  //输入的字符
  String words = '';
  //搜索展示的内容
  void searcherData(String text) {
    models.clear();
    words=text;
    if (text.isNotEmpty) {
      for (int i = 0; i < allModels.length; i++) {
        String name = allModels[i];
        if (name.contains(text)) {
          models.add(name);
        }
      }
    }
    setState(() {});
  }

  //控制取消符号是否显示
  bool _showClear = false;


  void _onChanged(String text) {
    searcherData(text);
    setState(() {
      _showClear = text.isNotEmpty;
    });
    // if (text.isNotEmpty) {
    //   setState(() {
    //     _showClear = true;
    //   });
    // } else {
    //   setState(() {
    //     _showClear = false;
    //   });
    // }
  }

  double screenWith(BuildContext context) {
    return MediaQuery.of(context).size.width;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: 900.0,
        color: Colors.grey[200],
        child: Column(
          children: [
            const SizedBox(
              height: 40.0,
            ),
            //搜索框
            Container(
              height: 44.0,
              color: Colors.grey[200],
              child: Row(
                children: [
                  Container(
                      width: screenWith(context) - 40,
                      height: 34.0,
                      margin: const EdgeInsets.only(left: 5, right: 5),
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(6.0),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.only(left: 8.0, right: 8.0),
                        // 右边留有一些空间
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            const Image(
                              image:
                                  AssetImage('images/Fav_Search_Icon@3x.png'),
                              width: 20,
                            ),
                            Expanded(
                              flex: 1,
                              child: TextField(
                                controller: _controller,
                                onChanged: _onChanged,
                                cursorColor: Colors.green,
                                style: const TextStyle(
                                  fontSize: 18.0,
                                  color: Colors.black,
                                  fontWeight: FontWeight.w300,
                                ),
                                decoration: const InputDecoration(
                                    contentPadding: EdgeInsets.only(
                                        left: 5.0, right: 5.0, bottom: 10.0),
                                    border: InputBorder.none,
                                    hintText: '搜索'),
                              ),
                            ),
                            _showClear
                                ? GestureDetector(
                                    onTap: () {
                                      setState(() {
                                        _controller.clear();
                                        _onChanged('');
                                      });
                                    },
                                    child: const Icon(Icons.cancel,
                                        color: Colors.grey),
                                  )
                                : Container(),
                          ],
                        ),
                      )),

                  GestureDetector(
                    onTap: () {
                      //返回首页
                      Navigator.pop(context);
                    },
                    child: const Text('取消'),
                  ),
                ],
              ),
            ),
            Expanded(
                child: ListView.builder(
                    itemCount: models.length,
                    itemBuilder: (BuildContext context, int index) {
                      return SearcherPeople(models[index],words);
                    }))
          ],
        ),
      ),
    );
  }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值