文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Flutter怎么实现自定义搜索框AppBar

2023-06-30 02:07

关注

这篇文章主要讲解了“Flutter怎么实现自定义搜索框AppBar”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Flutter怎么实现自定义搜索框AppBar”吧!

介绍

开发中,页面头部为搜索样式的设计非常常见,为了可以像系统AppBar那样使用,这篇文章记录下在Flutter中自定义一个通用的搜索框AppBar记录。

功能点: 搜索框、返回键、清除搜索内容功能、键盘处理。

效果图

Flutter怎么实现自定义搜索框AppBar

实现步骤

首先我们先来看下AppBar的源码,实现了PreferredSizeWidget类,我们可以知道这个类主要是控制AppBar的高度的,Scaffold脚手架里的AppBar的参数类型就是PreferredSizeWidget类型。

class AppBar extends StatefulWidget implements PreferredSizeWidget{...preferredSize = _PreferredAppBarSize(toolbarHeight, bottom?.preferredSize.height),.../// {@template flutter.material.appbar.toolbarHeight}/// Defines the height of the toolbar component of an [AppBar].////// By default, the value of `toolbarHeight` is [kToolbarHeight]./// {@endtemplate}final double? toolbarHeight;.../// The height of the toolbar component of the [AppBar].const double kToolbarHeight = 56.0;}abstract class PreferredSizeWidget implements Widget {  // 设置在不受约束下希望的大小  // 设置高度:Size.fromHeight(myAppBarHeight)  Size get preferredSize;}

为了方便扩展,可以在Scaffold里使用,我们需要创建AppBarSearch类继承有状态StatefulWidget类并实现PreferredSizeWidget类,实现preferredSize方法,并设置高度。

class AppBarSearch extends StatefulWidget implements PreferredSizeWidget {@overrideSize get preferredSize => Size.fromHeight(height);}

因为ScaffoldAppBar实现了状态栏的适配,核心见下方源码:

//获取状态栏高度MediaQuery.of(context).padding.top;

Flutter怎么实现自定义搜索框AppBar

这里我们直接返回AppBar,并进行改造。(当然这里也可以不返回AppBar我们自己处理状态栏的高度也行)。

思路: AppBar title字段自定义输入框,主要通过文本框监听实现清除搜索内容和显示清除按钮的功能,通过输入框是否有焦点监听进行刷新布局,通过定义回调函数的方式来进行搜索内容的监听。

// 输入框控制_controller = widget.controller ?? TextEditingController();// 焦点控制_focusNode = widget.focusNode ?? FocusNode();// 焦点获取失去监听_focusNode?.addListener(() => setState(() {}));// 文本输入监听_controller?.addListener(() => setState(() {}));

键盘搜素监听:

只需设置TextField的这两个属性即可。

textInputAction: TextInputAction.search,onSubmitted: widget.onSearch, //输入框完成触发

键盘弹出收起处理:

在iOS中键盘的处理是需要我们自己来进行处理的,我们需要的功能是点击搜索框之外的地方失去焦点从而关闭键盘,这里我使用了处理键盘的一个插件:flutter_keyboard_visibility: ^5.1.0,在我们需要处理焦点事件页面根布局使用KeyboardDismissOnTap外部包裹即可,这个插件还可以主动控制键盘的弹出和收起,有兴趣的小伙伴可以了解下。

return KeyboardDismissOnTap(    child: Material();

完整源码

/// 搜索AppBarclass AppBarSearch extends StatefulWidget implements PreferredSizeWidget {  AppBarSearch({    Key? key,    this.borderRadius = 10,    this.autoFocus = false,    this.focusNode,    this.controller,    this.height = 40,    this.value,    this.leading,    this.backgroundColor,    this.suffix,    this.actions = const [],    this.hintText,    this.onTap,    this.onClear,    this.onCancel,    this.onChanged,    this.onSearch,    this.onRightTap,  }) : super(key: key);  final double? borderRadius;  final bool? autoFocus;  final FocusNode? focusNode;  final TextEditingController? controller;  // 输入框高度 默认40  final double height;  // 默认值  final String? value;  // 最前面的组件  final Widget? leading;  // 背景色  final Color? backgroundColor;  // 搜索框内部后缀组件  final Widget? suffix;  // 搜索框右侧组件  final List<Widget> actions;  // 输入框提示文字  final String? hintText;  // 输入框点击回调  final VoidCallback? onTap;  // 清除输入框内容回调  final VoidCallback? onClear;  // 清除输入框内容并取消输入  final VoidCallback? onCancel;  // 输入框内容改变  final ValueChanged<String>? onChanged;  // 点击键盘搜索  final ValueChanged<String>? onSearch;  // 点击右边widget  final VoidCallback? onRightTap;  @override  _AppBarSearchState createState() => _AppBarSearchState();  @override  Size get preferredSize => Size.fromHeight(height);}class _AppBarSearchState extends State<AppBarSearch> {  TextEditingController? _controller;  FocusNode? _focusNode;  bool get isFocus => _focusNode?.hasFocus ?? false; //是否获取焦点  bool get isTextEmpty => _controller?.text.isEmpty ?? false; //输入框是否为空  bool get isActionEmpty => widget.actions.isEmpty; // 右边布局是否为空  bool isShowCancel = false;  @override  void initState() {    _controller = widget.controller ?? TextEditingController();    _focusNode = widget.focusNode ?? FocusNode();    if (widget.value != null) _controller?.text = widget.value ?? "";    // 焦点获取失去监听    _focusNode?.addListener(() => setState(() {}));    // 文本输入监听    _controller?.addListener(() {      setState(() {});    });    super.initState();  }  // 清除输入框内容  void _onClearInput() {    setState(() {      _controller?.clear();    });    widget.onClear?.call();  }  // 取消输入框编辑失去焦点  void _onCancelInput() {    setState(() {      _controller?.clear();      _focusNode?.unfocus(); //失去焦点    });    // 执行onCancel    widget.onCancel?.call();  }  Widget _suffix() {    if (!isTextEmpty) {      return InkWell(        onTap: _onClearInput,        child: SizedBox(          width: widget.height,          height: widget.height,          child: Icon(Icons.cancel, size: 22, color: Color(0xFF999999)),        ),      );    }    return widget.suffix ?? SizedBox();  }  List<Widget> _actions() {    List<Widget> list = [];    if (isFocus || !isTextEmpty) {      list.add(InkWell(        onTap: widget.onRightTap ?? _onCancelInput,        child: Container(          constraints: BoxConstraints(minWidth: 48.w),          alignment: Alignment.center,          child: MyText(            '搜索',            fontColor: MyColors.color_666666,            fontSize: 14.sp,          ),        ),      ));    } else if (!isActionEmpty) {      list.addAll(widget.actions);    }    return list;  }  @override  Widget build(BuildContext context) {    return AppBar(      backgroundColor: widget.backgroundColor,      //阴影z轴      elevation: 0,      // 标题与其他控件的间隔      titleSpacing: 0,      leadingWidth: 40.w,      leading: widget.leading ??          InkWell(            child: Icon(              Icons.arrow_back_ios_outlined,              color: MyColors.color_666666,              size: 16.w,            ),            onTap: () {              Routes.finish(context);            },          ),      title: Container(          margin: EdgeInsetsDirectional.only(end: 10.w),          height: widget.height,          decoration: BoxDecoration(            color: Color(0xFFF2F2F2),            borderRadius: BorderRadius.circular(widget.borderRadius ?? 0),          ),          child: Container(            child: Row(              children: [                SizedBox(                  width: widget.height,                  height: widget.height,                  child:                      Icon(Icons.search, size: 20.w, color: Color(0xFF999999)),                ),                Expanded(                  // 权重                  flex: 1,                  child: TextField(                    autofocus: widget.autoFocus ?? false,                    // 是否自动获取焦点                    focusNode: _focusNode,                    // 焦点控制                    controller: _controller,                    // 与输入框交互控制器                    //装饰                    decoration: InputDecoration(                      isDense: true,                      border: InputBorder.none,                      hintText: widget.hintText ?? '请输入关键字',                      hintStyle: TextStyle(                          fontSize: 14.sp, color: MyColors.color_666666),                    ),                    style: TextStyle(                      fontSize: 14.sp,                      color: MyColors.color_333333,                    ),                    // 键盘动作右下角图标                    textInputAction: TextInputAction.search,                    onTap: widget.onTap,                    // 输入框内容改变回调                    onChanged: widget.onChanged,                    onSubmitted: widget.onSearch, //输入框完成触发                  ),                ),                _suffix(),              ],            ),          )),      actions: _actions(),    );  }  @override  void dispose() {    _controller?.dispose();    _focusNode?.dispose();    super.dispose();  }}

感谢各位的阅读,以上就是“Flutter怎么实现自定义搜索框AppBar”的内容了,经过本文的学习后,相信大家对Flutter怎么实现自定义搜索框AppBar这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯