Flutter实现漂亮的搜索框

最终效果图:


import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

///圆角搜索框
class YmSearchBar extends StatefulWidget {

  ///搜索框上显示的文案
  String hint;
  ///搜索框的圆角
  double defaultBorderRadius;
  EdgeInsets margin;
  EdgeInsets padding;
  ///如果考虑不需要水波纹效果那么就可以设置颜色为透明色
  Color splashColor;
  ///文本输入框焦点控制
  FocusNode? focusNode;
  ///文本输入框控制器
  TextEditingController? controller;
  ///点击键盘上的回车键的回调
  Function(String text)? onSubmitted;
  ///清楚搜索回调
  Function? clearCallback;
  ///返回键的回调
  Function()? onBackCallback;
  ///输入文本的长度限制
  int inputKeyWordsLength;
  ///输入框文字大小
  double fontSize;
  ///是否显示左侧的返回键
  bool isShowBackButton;
  ///搜索框的长度
  double width;
  ///搜索框的高度
  double height;

  YmSearchBar(
      {
        this.hint = "搜索",
        this.defaultBorderRadius = 30.0,
        this.margin = const EdgeInsets.only(top: 10.0, bottom: 10.0),
        this.padding = const EdgeInsets.only(left: 12),
        this.splashColor = const Color(0xFFD6D6D6),
        this.focusNode,
        this.controller,
        this.onSubmitted,
        this.onBackCallback,
        this.clearCallback,
        this.inputKeyWordsLength = 20,
        this.fontSize = 14,
        this.isShowBackButton = false,
        this.width = 200,
        this.height = 60
      }
    ) {
          this.height = this.defaultBorderRadius * 2;
  }

  @override
  State createState() {
    return SearchTextFieldBarState();
  }
}

class SearchTextFieldBarState extends State {

  ///为true 时显示清除选项
  bool showClear = false;
  ///文本输入框的默认使用控制器
  TextEditingController defaultTextController = TextEditingController();

  @override
  void initState() {
    super.initState();
    ///创建默认的焦点控制
    if (widget.focusNode == null) {
      widget.focusNode = new FocusNode();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      ///外边距
      margin: widget.margin,
      ///水平方向线性排列
      child: Row(
        children: [
          ///左侧的返回按钮
          buildLeftBackWidget(),
          ///右侧的搜索框内容区域
          buildContentContainer(),
        ],
      ),
    );
  }

  ///构建左侧的返回按钮
  Widget buildLeftBackWidget() {
    ///当用在APPBar的位置时
    ///常常需要配合一个返回按钮
    if (widget.isShowBackButton) {
      ///返回键按钮
      return BackButton(
        color: Colors.white,
        onPressed: () {
          ///返回事件回调
          if (widget.onBackCallback != null) {
            widget.onBackCallback!();
          } else {
            ///直接关闭当前页面
            Navigator.of(context).pop();
          }
        },
      );
    } else {
      ///当不需要显示返回按钮时
      ///设置一个空视图
      return Container();
    }
  }

  ///构建搜索框的显示区域[Container]
  LayoutBuilder buildContainer(BuildContext context) {
    return LayoutBuilder(builder: (context, BoxConstraints constraints) {
      return buildContentContainer();
    });
  }

  ///构建搜索框的显示区域[Container]
  Container buildContentContainer() {
    return Container(
      height: widget.height,
      ///获取当前StatelessWidget的宽度
      width: widget.width,
      ///对齐方式
      alignment: Alignment(-1, 0),
      ///内边距
      padding: widget.padding,
      ///圆角边框
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(widget.defaultBorderRadius),
      ),
      child: buildRow(),
    );
  }

  ///构建搜索图标与显示文本
  Row buildRow() {
    return Row(
      ///左对齐
      mainAxisAlignment: MainAxisAlignment.start,
      ///居左
      crossAxisAlignment: CrossAxisAlignment.center,
      children:[
        ///左侧的搜索图标
        Icon(
          Icons.search,
          color: Colors.pink,
          size: 24.0,
          semanticLabel: 'Text to announce in accessibility modes',
        ),

        SizedBox(
          width: 8.0,
        ),
        ///中间的输入框
        Expanded(
          flex: 1,
          child: Container(
            alignment: Alignment(-1, 0),
            child: buildTextField(),
          ),
        ),
        ///右侧的清除小按钮
        buildClearButton(),
      ],
    );
  }


  ///lib/demo/search_textfield_bar.dart
  ///构建搜索输入TextField
  TextField buildTextField() {
    return TextField(
      ///设置键盘的类型
      keyboardType: TextInputType.text,
      ///键盘回车键的样式为搜索
      textInputAction: TextInputAction.search,
      ///只有苹果手机上有效果
      keyboardAppearance: Brightness.dark,
      ///控制器配置
      controller:
      widget.controller == null ? defaultTextController : widget.controller,

      ///最大行数
      maxLines: 1,

      ///输入文本格式过滤
      inputFormatters: [
        ///输入的内容长度限制
        LengthLimitingTextInputFormatter(widget.inputKeyWordsLength),
      ],

      ///当输入文本时实时回调
      onChanged: (text) {
        ///多层判断 优化刷新
        ///只有当有改变时再刷新
        if (text.length > 0) {
          if (!showClear) {
            showClear = true;
            setState(() {});
          }
        } else {
          if (showClear) {
            showClear = false;
            setState(() {});
          }
        }
      },

      ///点击键盘上的回车键
      ///或者是搜索按钮的回调
      onSubmitted: (text) {
        if (widget.onSubmitted != null) {
          widget.onSubmitted!(text);
        }
      },

      ///输入框不自动获取焦点
      autofocus: false,
      focusNode: widget.focusNode,

      style: TextStyle(
          fontSize: widget.fontSize,
          color: Colors.black54,
          fontWeight: FontWeight.w300),

      ///输入框的边框装饰
      decoration: InputDecoration(
        //重要 用于编辑框对齐
          isDense: true,
          ///清除文本内边跑
          contentPadding: EdgeInsets.zero,
          ///不设置边框
          border: InputBorder.none,
          ///设置提示文本
          hintText: widget.hint,
          ///设置提示文本的样式
          hintStyle: TextStyle(
            fontSize: widget.fontSize,
            color: Color(0xff999999),
          )),
    );
  }

  ///清除按键
  ///当文本框有内容输入时显示清除按钮
  buildClearButton() {
    ///当文本输入框中有内容时才显示清除按钮
    if (showClear) {
      return IconButton(
        icon: Icon(
          Icons.clear,
          size: 24.0,
          color: Color(0xffacacac),
        ),
        onPressed: () {
          if(widget.controller==null){
            defaultTextController.clear();
          }else{
            widget.controller!.text = "";
          }
          if (widget.clearCallback != null) {
            widget.clearCallback!();
          }
        },
      );
    } else {
      return Container();
    }
  }
}

把这个文件放到任意位置,使用:

child: YmSearchBar(
       hint: "关键词",
       width: MediaQuery.of(context).size.width - 40,
       onSubmitted: (text){
            print("搜索$text");
            _searchTextValue = text;
            _loadData();

        },
        clearCallback:(){
            _searchTextValue = "";
            _loadData();
        },
        onBackCallback: () {

        }
),


本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。

 关于作者
 热门教程
通过Git下载和提交代码的命令记录
安装好git后: 1、配置邮箱 git config --global user.name ymbok git con
2023-08-15
剑道仙尊
59
通过ADB在Android系统中快捷截屏和录屏的方法
连上ADB线后: 截图 创建一个BAT文件,用于截图,直接双击运行即可将图片保存到D:\screenshot目录,提前
2023-08-15
剑道仙尊
105
Android12 源码下载与编译
下载Android12 源码 sudo apt-get update 安装curl sudo apt install
2023-04-25
剑道仙尊
125
android生成签名文件jks并获取SHA1
打开Android Studio终端,输入: keytool -genkey -alias app -keyalg R
2022-07-13
剑道仙尊
93
Flutter开发APP更改状态栏文字颜色
void main(){ runApp(MyApp()); /// 状态栏文字黑色 SystemChrome
2022-06-09
剑道仙尊
132
Android Swicth按钮样式自定义
<Switch android:id="@+id/switch_btn" android:layout_wi
2022-06-07
剑道仙尊
133
Pagging3写起来太麻烦,简单封装及其简单
Pagging3分页写起来很麻烦,这里分享一下我的简化开发的方法,思路就是把获取数据的函数分离出来 首先定义一个基础的
2022-06-07
剑道仙尊
187
在项目中使用Hilt Retrofit使用总结
直接开始,首先我们看看怎么使用Hilt编写 Retrofit 接口请求类 用@Provides注解定义可注入的实例的提
2022-06-07
剑道仙尊
197
Android Jetpack Paging 3 下拉刷新和加载更多代码示例
使用Paging3实现列表的下拉刷新和加载更多 首先定义列表布局文件 <androidx.swiperefres
2022-06-07
剑道仙尊
434
StatefulBuilder实现Dialog的刷新
在Flutter中使用Dialog时,因为 showDialog返回的context与当前页面的 context不是同
2022-06-07
剑道仙尊
136