美文网首页大前端-BFEFlutter
Flutter自定义带搜索框的AppBar

Flutter自定义带搜索框的AppBar

作者: buhuiming | 来源:发表于2019-02-18 15:28 被阅读1840次

    刚起步学习Flutter,还是比较容易上手的。下面介绍一下自定义的带搜索框的AppBar。

    项目地址(github


    效果图

    image.png
    image.png

    1、集成自StatefulWidget,声明属性,注意:这里要实现PreferredSizeWidget,否则不能作为appBar控件引用;

    class SearchAppBarWidget extends StatefulWidget implements PreferredSizeWidget {
      final double height;
      final double elevation; //阴影
      final Widget leading;
      final String hintText;
      final FocusNode focusNode;
      final TextEditingController controller;
      final IconData prefixIcon;
      final List<TextInputFormatter> inputFormatters;
      final VoidCallback onEditingComplete;
    
      const SearchAppBarWidget(
          {Key key,
          this.height: 46.0,
          this.elevation: 0.5,
          this.leading,
          this.hintText: '请输入关键词',
          this.focusNode,
          this.controller,
          this.inputFormatters,
          this.onEditingComplete,
          this.prefixIcon: Icons.search})
          : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return new SearchAppBarState();
      }
    
      @override
      // TODO: implement preferredSize
      Size get preferredSize => Size.fromHeight(height);//这里设置控件(appBar)的高度
    }
    

    2、SearchAppBarState,这里使用的是PreferredSizeWidget 的实现类PreferredSize,用Stack和Offstage让两个布局(常规的appBar和输入框)重合在一起;

    class SearchAppBarState extends State<SearchAppBarWidget> {
      bool _hasdeleteIcon = false;
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return new PreferredSize(
            child: new Stack(
              children: <Widget>[
                new Offstage(
                  offstage: false,
                  child:
                      MoreWidgets.buildAppBar(context, '', leading: widget.leading),
                ),
                new Offstage(
                    offstage: false,
                    child: Container(
                        padding: const EdgeInsets.only(left: 30.0, top: 26.0),
                        child: new TextField(
                            focusNode: widget.focusNode,
                            keyboardType: TextInputType.text,
                            textInputAction: TextInputAction.done,
                            controller: widget.controller,
                            maxLines: 1,
                            inputFormatters: widget.inputFormatters,
                            decoration: InputDecoration(
                              hintText: widget.hintText,
                              hintStyle: TextStyle(
                                color: Colors.black,
                                fontSize: 16.5,
                              ),
                              prefixIcon: Padding(
                                  padding: EdgeInsetsDirectional.only(start: 24.0),
                                  child: Icon(
                                    widget.prefixIcon,
                                    color: Colors.black,
                                  )),
                              suffixIcon: Padding(
                                  padding: EdgeInsetsDirectional.only(
                                      start: 2.0, end: _hasdeleteIcon ? 20.0 : 0),
                                  child: _hasdeleteIcon
                                      ? new InkWell(
                                          onTap: (() {
                                            setState(() {
                                              widget.controller.text = '';
                                              _hasdeleteIcon = false;
                                            });
                                          }),
                                          child: Icon(
                                            Icons.clear,
                                            size: 18.0,
                                            color: Colors.black,
                                          ))
                                      : new Text('')),
                              contentPadding: EdgeInsets.fromLTRB(0, 10, 0, 0),
                              filled: true,
                              fillColor: Colors.transparent,
                              border: InputBorder.none,
                            ),
                            onChanged: (str) {
                              setState(() {
                                if (str.isEmpty) {
                                  _hasdeleteIcon = false;
                                } else {
                                  _hasdeleteIcon = true;
                                }
                              });
                            },
                            onEditingComplete: widget.onEditingComplete)))
              ],
            ),
            preferredSize: Size.fromHeight(widget.height));
      }
    }
    
     static Widget buildAppBar(BuildContext context, String text,
          {double fontSize: 18.0,
          double height: 46.0,
          double elevation: 0.5,
          Widget leading,
          bool centerTitle: false}) {
        return new PreferredSize(
            child: new AppBar(
                elevation: elevation, //阴影
                centerTitle: centerTitle,
                title: Text(text, style: TextStyle(fontSize: fontSize)),
                leading: leading),
            preferredSize: Size.fromHeight(height));
      }
    

    3、引用

     appBar: new SearchAppBarWidget(
                  focusNode: _focusNode,
                  controller: _controller,
                  elevation: 2.0,
                  leading: IconButton(
                      icon: Icon(Icons.arrow_back),
                      onPressed: () {
                        Navigator.pop(context);
                      }),
                  inputFormatters: [
                    LengthLimitingTextInputFormatter(50),
                  ],
                  onEditingComplete: () => _checkInput()),
    
    至此,一个简单带搜索框的appBar就完成了,外部引用和TextField差不多,需要扩展的属性可以自行添加。

    相关文章

      网友评论

        本文标题:Flutter自定义带搜索框的AppBar

        本文链接:https://www.haomeiwen.com/subject/nfbaeqtx.html