Flutter-当文本可见时,Textfield失去焦点

时间:2020-01-20 20:30:48

标签: flutter dart

在我的项目中,我为密码创建了一个文本字段,并制定了一种显示和隐藏密码的方法。发生的事情是,当我按下图标显示文本时,键盘和光标消失了,我的意思是失去了焦点。

当我按下图标时,如何使它不失去焦点?谢谢

class ExampleLoginFocus extends StatefulWidget {
  @override
  _ExampleLoginFocusState createState() => _ExampleLoginFocusState();
}

class _ExampleLoginFocusState extends State<ExampleLoginFocus> {
  FocusNode focusPass;

  var pass = '';
  bool passwordVisible;

  @override
  void initState() {
    super.initState();
    passwordVisible = true;
    focusPass = FocusNode();
  }

  Widget password() {
    return TextField(
      obscureText: passwordVisible,
      focusNode: focusPass,
      decoration: InputDecoration(
        suffixIcon: Padding(
          padding: EdgeInsets.only(top: 20, bottom: 0),
            child: IconButton(
          icon: Icon(
            passwordVisible ? Icons.visibility_off : Icons.visibility,
            color: Theme.of(context).primaryColorDark,
          ),
          onPressed: () {
            setState(() {
              passwordVisible = !passwordVisible;
            });
          },
        )),
      ),
      onChanged: (String tex) {
        pass = tex;
        print(pass);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: password(),
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

我无法测试您的代码,但是我有一个自定义文本字段小部件,该小部件允许使用属性来定义是通用文本字段还是密码文本字段,也许这对您有帮助

class DnetTextField extends StatefulWidget {
  final String label;
  final bool isPasswordField;
  final TextEditingController controller;
  final TextInputType textInputType;
  final TextInputAction textInputAction;
  final FormFieldValidator validator;
  final IconData icon;
  final Color color;
  final Color errorColor;
  final BuildContext context;
  final FocusNode currentFocus;
  final FocusNode nextFocus;
  final bool autoValidate;
  final double width;
  final ValueChanged<String> onFieldSubmitted;
  final List<TextInputFormatter> inputFormatters;
  final TextCapitalization textCapitalization;
  final int maxLength;
  final bool focusable;
  final String hint;

  DnetTextField({
    @required this.context,
    @required this.label,
    @required this.controller,
    this.icon,
    this.color,
    this.errorColor,
    this.textInputType = TextInputType.text,
    this.textInputAction = TextInputAction.done,
    this.validator,
    this.isPasswordField = false,
    this.currentFocus,
    this.nextFocus,
    this.onFieldSubmitted,
    this.autoValidate = false,
    this.width = 266,
    this.inputFormatters,
    this.textCapitalization = TextCapitalization.none,
    this.maxLength = -1,
    this.focusable = true,
    this.hint,
  });

  @override
  DnetTextFieldState createState() {
    return DnetTextFieldState();
  }
}

class DnetTextFieldState extends State<DnetTextField> {
  bool hasErrors = false;
  bool passwordVisible = false;

  Color get currentColor => hasErrors ? widget.errorColor : widget.color;

  IconData get currentIcon {
    if (widget.isPasswordField) if (passwordVisible)
      return Icons.visibility_off;
    else
      return Icons.visibility;
    else
      return widget.icon;
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final border = OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(10.0)),
      borderSide: BorderSide(color: currentColor),
    );

    final focusableTheme = widget.focusable
        ? Theme.of(context)
        : Theme.of(
            context,
          ).copyWith(
            splashFactory: const NoSplashFactory(),
          );

    return Container(
      width: widget.width,
      height: 80,
      child: Theme(
        data: focusableTheme,
        child: TextFormField(
          inputFormatters: widget.inputFormatters,
          style: TextStyle(color: currentColor),
          controller: widget.controller,
          keyboardType: widget.textInputType,
          textInputAction: widget.textInputAction,
          enableInteractiveSelection: widget.focusable,
          focusNode:
              widget.focusable ? widget.currentFocus : DnetDisabledFocusNode(),
          decoration: InputDecoration(
            hintText: widget.hint,
            suffixIcon: getSuffixIcon(),
            fillColor: currentColor,
            labelText: widget.label,
            labelStyle:
                TextStyle(color: currentColor, fontStyle: FontStyle.italic),
            focusedBorder: border,
            enabledBorder: border,
            border: border,
          ),
          autovalidate: widget.autoValidate,
          validator: (text) {
            final validatorMessage =
                widget.validator == null ? null : widget.validator(text);
            setHasErrors(validatorMessage != null);
            if (validatorMessage != null) return validatorMessage;
          },
          onFieldSubmitted: widget.onFieldSubmitted ??
              (term) {
                if (widget.nextFocus != null) {
                  FocusScope.of(context).requestFocus(widget.nextFocus);
                }
              },
          obscureText: widget.isPasswordField && !passwordVisible,
          textCapitalization: widget.textCapitalization,
          maxLength: widget.maxLength != -1 ? widget.maxLength : null,
        ),
      ),
    );
  }

  setHasErrors(bool errors) {
    setState(() {
      hasErrors = errors;
    });
  }

  setPasswordVisible(bool visible) {
    setState(() {
      passwordVisible = visible;
    });
  }

  GestureDetector getSuffixIcon() {
    if (widget.icon != null || widget.isPasswordField) {
      return GestureDetector(
        child: Icon(
          currentIcon,
          color: currentColor,
        ),
        onTap: () {
          if (widget.isPasswordField) setPasswordVisible(!passwordVisible);
        },
      );
    } else {
      return null;
    }
  }
}