Flutter 漂亮的搜索框密码框

这个博客介绍了如何在Flutter中创建一个自定义的SearchPwdTextField组件,该组件包括文本输入、密码切换、删除按钮、自定义图片等功能,并且允许设置输入格式、回调函数等参数。示例代码展示了组件的完整实现和使用方法。
摘要由CSDN通过智能技术生成

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


const Color _textColor = Colors.black;
const TextStyle _textStyle = TextStyle(fontSize: 15.0,color: _textColor);
const TextStyle _hintTextStyle = TextStyle(fontSize: 15.0,color: Color(0xFFBBBBBB));

typedef _InputCallBack = void Function(String value);

class SearchPwdTextField extends StatefulWidget {

  final String text;
  final String hintText;
  final String labelText;//top提示文字
  final TextEditingController controller;
  final TextInputType keyboardType;
  final FocusNode focusNode;
  final bool isPwd; //是否是密码,默认不是
  final Widget leftWidget; //左侧widget ,默认隐藏
  final Widget rightWidget; //右侧widget ,默认隐藏
  final int maxLength; //最大长度,默认20
  final bool isShowDeleteBtn;  //是否显示右侧删除按钮,默认不显示
  final List<TextInputFormatter> inputFormatters;
  final _InputCallBack inputCallBack;
  final String pwdOpen; //自定义密码图片路径 睁眼
  final String pwdClose;//自定义密码图片路径 闭眼
  final InputBorder border; //边框样式
  final bool isDense; //是否紧凑显示,默认false


  const SearchPwdTextField({
    Key key,
    this.text: '',
    this.keyboardType: TextInputType.text,
    this.hintText: '',
    this.labelText,
    this.controller,
    this.focusNode,
    this.isPwd = false,
    this.leftWidget,
    this.rightWidget,
    this.maxLength:20,
    this.isShowDeleteBtn = false,
    this.inputFormatters,
    this.inputCallBack,
    this.pwdOpen,
    this.pwdClose,
    this.border,
    this.isDense:false,

  }): super(key: key);

  @override
  _SearchPwdTextFieldState createState() => _SearchPwdTextFieldState();
}

class _SearchPwdTextFieldState extends State<SearchPwdTextField> {


   TextEditingController _textController;
   FocusNode _focusNode;
   bool _isShowDelete;
   bool _isHideenPwdBtn; //是否隐藏 右侧密码明文切换按钮 ,密码样式才显示(isPwd =true),
   bool _pwdShow; //控制密码 明文切换
   Widget _pwdImg; //自定义密码图片
   bool _isShowRight=false;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    _textController = widget.controller!=null ? widget.controller : TextEditingController();
    _textController.text = widget.text;
    _focusNode = widget.focusNode !=null ?widget.focusNode : FocusNode();
    _isHideenPwdBtn = !widget.isPwd ;
    _pwdShow = widget.isPwd;

    _isShowDelete = _focusNode.hasFocus && _textController.text.isNotEmpty;
    _textController.addListener(() {
      setState(() {
        _isShowDelete = _textController.text.isNotEmpty &&_focusNode.hasFocus;
      });
    });
    _focusNode.addListener(() {
      setState(() {
        _isShowDelete = _textController.text.isNotEmpty &&_focusNode.hasFocus;
      });
    });

  }

  @override
  Widget build(BuildContext context) {

    if(widget.pwdOpen!=null && widget.pwdClose!=null){
      if(widget.pwdOpen.isNotEmpty && widget.pwdClose.isNotEmpty){
        _pwdImg = _pwdShow ? ImageIcon(AssetImage(widget.pwdClose)):ImageIcon(AssetImage(widget.pwdOpen)) ;
      }else{
        _pwdImg = Icon(_pwdShow ? Icons.visibility_off : Icons.visibility);
      }
    }else{
      _pwdImg = Icon(_pwdShow ? Icons.visibility_off : Icons.visibility);
//      _pwdImg = _pwdShow?Image.asset("assets/images/ic_pwd_close.png",width: 18.0,):Image.asset("assets/images/ic_pwd_open.png",width: 18.0,);
//      _pwdImg = _pwdShow?ImageIcon(AssetImage("assets/images/ic_pwd_close.png")):ImageIcon(AssetImage("assets/images/ic_pwd_open.png")) ;
    }

    return

      Stack(
        alignment: Alignment.centerRight,
        children: <Widget>[

          TextField(
            focusNode: _focusNode,
            controller: _textController,
            keyboardType: widget.keyboardType,
            style: _textStyle,
//            // 数字、手机号限制格式为0到9(白名单), 密码限制不包含汉字(黑名单)
//            inputFormatters: (widget.keyboardType == TextInputType.number || widget.keyboardType == TextInputType.phone) ?
//            [WhitelistingTextInputFormatter(RegExp('[0-9]'))] : [BlacklistingTextInputFormatter(RegExp('[\u4e00-\u9fa5]'))],
            inputFormatters: widget.inputFormatters!=null ?widget.inputFormatters:[LengthLimitingTextInputFormatter(widget.maxLength)],
            decoration: InputDecoration(
              prefixIcon: widget.leftWidget,
              labelText: widget.labelText!= null ?widget.labelText: null,
              hintText:  widget.hintText,
              hintStyle: _hintTextStyle,
              isDense: widget.isDense,
              enabledBorder: widget.border!=null?widget.border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 0.8)),
              focusedBorder: widget.border!=null?widget.border: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 0.8)),
//          suffixIcon:
            ),
            obscureText: _pwdShow,
            onChanged: (value){

              if(widget.inputCallBack!=null){
                _isShowRight=value.isNotEmpty;
                widget.inputCallBack(_textController.text);
              }
            },
          ),

          Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Offstage(offstage: !widget.isShowDeleteBtn, child:
              _isShowDelete
                  ? IconButton(icon: Icon(Icons.cancel,color: Color(0xFFC8C8C8),size: 20,),
                  onPressed: (){
                    _textController.text = "";
                    if(widget.inputCallBack!=null){
                      _isShowRight=_textController.text.isNotEmpty;
                      widget.inputCallBack(_textController.text);
                    }
                  }
              ): Text(""),
              ),
              Offstage( offstage: _isHideenPwdBtn, child:
              IconButton(
//                  icon: Icon(_pwdShow ? Icons.visibility_off : Icons.visibility),
//                  icon: Image.asset("assets/images/ic_pwd_close.png",width: 18.0,),
                icon: _pwdImg,
                iconSize: 18.0 ,
                onPressed: () {
                  setState(() {
                    _pwdShow = !_pwdShow;
                  });
                },
              )
              ),
              widget.rightWidget!=null&&_isShowRight?widget.rightWidget:Container(),
            ],
          ),
        ],
      );


//以下代码添加右侧自定义widget点击会弹出键盘


     TextField(
       focusNode: _focusNode,
       controller: _textController,
       keyboardType: widget.keyboardType,
       style: _textStyle,
       inputFormatters: widget.inputFormatters!=null ?widget.inputFormatters:[LengthLimitingTextInputFormatter(20)],
       decoration: InputDecoration(
         hintText:  widget.hintText,
         hintStyle: _hintTextStyle,
         focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 0.8)),
         enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color:  Colors.grey,width: 0.5)),
         prefixIcon: widget.leftWidget,
         suffixIcon:
         Container(
           child: Row(
             mainAxisSize: MainAxisSize.min,
             children: <Widget>[
               Offstage(offstage: !widget.isShowDeleteBtn, child:
               _isShowDelete
                   ? IconButton(icon: Icon(Icons.cancel,color: Color(0xFFC8C8C8),size: 20,),
                   onPressed: (){
                     _textController.text = "";
                     if(widget.inputCallBack!=null){
                       widget.inputCallBack(_textController.text);
                     }
                   }
               ): Text(""),
               ),
               Offstage( offstage: _isHideenPwdBtn, child:
               IconButton(
//                  icon: Icon(_pwdShow ? Icons.visibility_off : Icons.visibility),
//                  icon: Image.asset("assets/images/ic_pwd_close.png",width: 18.0,),
                 icon: _pwdImg,
                 iconSize: 18.0 ,
                 onPressed: () {
                   setState(() {
                     _pwdShow = !_pwdShow;
                   });
                 },
               )
               ),
               widget.rightWidget!=null?widget.rightWidget:Container(),

             ],
           ),
         ),
       ),
       obscureText: _pwdShow,
       onChanged: (value){
         if(widget.inputCallBack!=null){
           widget.inputCallBack(_textController.text);
         }
       },
     );


  }
}

使用

 SearchPwdTextField(
            leftWidget: Icon(Icons.search, size: 25),
            hintText: '搜索想要的资源',
            isShowDeleteBtn: true,
            isDense: true,
            border: InputBorder.none,
            rightWidget:  Container(
              margin: EdgeInsets.only(right: 12),
              child: RawChip(
                  onPressed: () {
                    _onRefresh();
                  },
                  label: Text(
                    "搜索",
                    style: TextStyle(color: Colors.white),
                  ),
                  backgroundColor: Colors.orangeAccent),
            ),
            inputCallBack: (value) {

              setState(() {
                _search=value;
              });
              //删除关键字的时候也要刷新
              if(_search.isEmpty){
                _onRefresh();
              }

            },
          ),
        ),

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安果移不动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值