TextFormField 上的可点击图标 - 禁用 TextFormField 对图标单击的关注(颤振)

Posted

技术标签:

【中文标题】TextFormField 上的可点击图标 - 禁用 TextFormField 对图标单击的关注(颤振)【英文标题】:Clickable icon on TextFormField - disable TextFormField focus on icon click (Flutter) 【发布时间】:2020-01-25 13:37:30 【问题描述】:

我需要一个带有 suffixIcon 的 textField,但单击该图标后,我不需要打开键盘。如果没有 suffixIcon,我该如何做呢?

【问题讨论】:

令人困惑。你想要一个带有后缀图标的文本字段吗?您想为后缀图标添加功能(使其可点击..)吗?您希望文本字段可聚焦吗? 我想要 TextField 内的可点击图标,但是当我点击它时不显示键盘。 TextField 具有readOnly 属性,如果设置为true,则不会显示键盘。 那么我将无法将一些数据放入 textField。我想如果我点击文本字段写一些文本,但如果我点击 suffixIcon 不显示键盘并执行一些操作 【参考方案1】:
Container(
  child: Stack(
    alignment: Alignment.centerRight,
    children: <Widget>[
      TextField(),
      IconButton(
        icon: Icon(Icons.image),
        onPressed: () 
          // do something
        ,
      ),
    ],
  ),
)

【讨论】:

当TextField下方出现错误时,此解决方案不起作用,它使按钮不再垂直居中【参考方案2】:

经过测试和确认,正是您想要的。

Stack(
  alignment: Alignment.centerRight,
  children: <Widget>[
    TextField(
      keyboardType: TextInputType.text,
      style: Theme.of(context).textTheme.body1,
      obscureText: true,
      decoration: InputDecoration(
        labelText: 'Password',
        contentPadding: const EdgeInsets.fromLTRB(6, 6, 48, 6), // 48 -> icon width
      ),
    ),
    IconButton(
      icon: Icon(Icons.dialpad, color: const Color(0xfff96800)),
      onPressed: () 
        FocusScope.of(context).requestFocus(FocusNode());
        // Your codes...
      ,
    ),
  ],
),

【讨论】:

【参考方案3】:

这个问题还有一个可能的解决方法 - 取自这里:https://github.com/flutter/flutter/issues/39376 - 使用标准的 TextField 和一个按钮作为 suffixIcon,然后,魔术技巧:

InputDecoration(labelText: "Email address",
    border: OutlineInputBorder(),
    suffixIcon: IconButton(
    iconSize: 40,
    icon: Icon(Icons.fingerprint),
    onPressed: () async 
      focusNode.unfocus();
      focusNode.canRequestFocus = false;
      await performBiometricLogin();
      focusNode.canRequestFocus = true;
    ,
  ),
),

在这种情况下您必须注意两件事:

a) 在你的小部件中声明 focusNode(我在我的 statefull 小部件的状态类中这样做),然后将它用于你的文本字段:

FocusNode focusNode = FocusNode();

并在 TextField 中使用名为 focusNode 的属性:

focusNode: focusNode,

b) 如果您没有在 onPressed 事件处理程序中执行任何异步操作,那么您必须完全遵循 github 问题中的逻辑 - 一段时间后启用 canRequestFocus:

Future.delayed(Duration(milliseconds: 100), () 
    widget.textFieldFocusNode.canRequestFocus = true;
);

希望它能像帮助我一样帮助其他人。

谢谢。

【讨论】:

这很完美,无需堆栈即可保持 TextField 的清洁。我添加了一件事,因为如果 textField 被聚焦并且 suffixIcon 被点击,我不想失去焦点。在点击处理程序中添加 """if (textFieldFocusNode.hasPrimaryFocus) return;"""" 完成了这项工作。完整答案在这里***.com/questions/49125064/…【参考方案4】:

使用readOnly,不要使用enabled

【讨论】:

【参考方案5】:

单击而不打开键盘?如果是这样,只需创建一个类并将其分配给focusNode,将hasFocus 设置为false,如下所示:

class AlwaysDisabledFocusNode extends FocusNode 
  @override
  bool get hasFocus => false;


new TextField(
focusNode: AlwaysDisabledFocusNode(),
onTap: () ,
keyboardType: TextInputType.text,
decoration: InputDecoration(
border: InputBorder.none,
icon: Icon(Icons.apps),
hintText: 'Password'),
style: Theme.of(context).textTheme.body1,
),

readOnly: true 会在点击时更改图标颜色

new TextField(readOnly: true,
    //focusNode: AlwaysDisabledFocusNode(),
    onTap: () ,
    keyboardType: TextInputType.text,
    decoration: InputDecoration(
    border: InputBorder.none,
    icon: Icon(Icons.apps),
    hintText: 'Password'),
    style: Theme.of(context).textTheme.body1,
    ),

我认为您必须将RowTextFieldIconButton 放在一起,并使用单独的操作。

new Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    new Expanded(
        child: Padding(
      child: new TextField(
        onTap: () //action of TextField
        ,
        keyboardType: TextInputType.text,
        decoration: InputDecoration(
            border: InputBorder.none, hintText: 'Password'),
        style: Theme.of(context).textTheme.body1,
      ),
      padding: EdgeInsets.only(left: 40),
    )),
    IconButton(
      icon: Icon(Icons.apps),
      onPressed: () //action of iconbutton
      ,
    )
  ],
)

【讨论】:

我想如果我点击文本字段写一些文本,但如果我点击 suffixIcon 不显示键盘并执行一些操作 当您单击 textField 和单击图标时,您在两个选项中都有键盘。只有当我点击 textField 时我才需要键盘【参考方案6】:

我也做到了

Container(
        height: 40,
        child: Stack(
          children: <Widget>[
            TextField(
              controller: textEditingController,
              keyboardType: TextInputType.text,
              decoration: InputDecoration(
                prefixIcon: Icon(HelageeIcons.search_icon_of_search_box),
                border: OutlineInputBorder(
                  borderSide: BorderSide(
                    color: Color(0xff575656),
                  ),
                  borderRadius: const BorderRadius.all(
                    const Radius.circular(50.0),
                  ),
                ),
                hintStyle:
                    TextStyle(color: Color(0xffADADAC), fontSize: 14),
                hintText: "Quick Search",
              ),
            ),
            Positioned(
              right: 0,
              child: Container(
                height: 40,
                width: 40,
                child: Container(
                  child: Material(
                      shape: CircleBorder(),
                      color: Colors.transparent,
                      child: InkWell(
                          customBorder: CircleBorder(),
                          onTap: () ,
                          splashColor: Colors.grey,
                          child: Icon(Icons.keyboard))),
                ),
              ),
            ),
          ],
        ),
      ),

【讨论】:

【参考方案7】:

添加后缀图标和后缀图标点击文本字段,在我的情况下我使用如下

TextFormField(
    textInputAction: TextInputAction.done,
    maxLines: 1,
    obscureText: _obscureText,
    autofocus: false,
    focusNode: _passwordFocus,
    style: TextStyle(fontSize: 17.0, color: Colors.black),
    onFieldSubmitted: (term) 
      _passwordFocus.unfocus();
      _validateAndSubmit();
    ,
    decoration: InputDecoration(
      hintText: HINT_PASSWORD,
      hintStyle: TextStyle(fontSize: 17.0, color: Colors.black54),
      focusedBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.black),
      ),
      enabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.black87),
      ),
      errorBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.red),
      ),
      disabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.black87),
      ),
      focusedErrorBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Colors.red),
      ),
      labelText: HINT_PASSWORD,
      labelStyle: TextStyle(fontSize: 17.0, color: Colors.black),
      errorStyle: TextStyle(fontSize: 12.0, color: Colors.red),
      prefixIcon: Icon(
        Icons.lock,
        color: themeColor,
      ),
      /// magic is here suffix ixon click
      suffixIcon: IconButton(
        icon: Icon(
          // Based on passwordVisible state choose the icon
          _obscureText ? Icons.visibility : Icons.visibility_off,
          color: themeColor,
        ),
        onPressed: () 
          // Update the state i.e. toogle the state of passwordVisible variable
          setState(() 
            _obscureText ? _obscureText = false : _obscureText = true;
          );
        ,
      ),
    ),
    validator: validatePassword,
    onSaved: (value) => _password = value,
  )

【讨论】:

单击 suffixIcon 时您有活动键盘。它对我无效。【参考方案8】:

这应该可以工作

Stack(
            alignment: Alignment.centerRight,
            children: <Widget>[
              TextFormField(
              ),
              FlatButton(
                onPressed: () 
                  _openOrhidePassword();
                ,
                child: Image(
                  height: 24.0,
                  width: 24.0,
                  image: AssetImage('images/Eye.png'),
                ),
              ),
            ],
          ),

在我的情况下,图像大小是另一个问题。当我提供尺寸时,它可以很好地与其他小部件一起使用。

【讨论】:

以上是关于TextFormField 上的可点击图标 - 禁用 TextFormField 对图标单击的关注(颤振)的主要内容,如果未能解决你的问题,请参考以下文章

fullcalendar 为放置在事件上的可点击图标取消绑定 eventClick 方法

如何在TextFormField下方的errorText中添加图标?

如何在TextFormField的hintText中添加图标

setIcon() 更改图标但不更改具有大量标记的地图上的可寻址 DOM

在颤动中从 TextFormField 添加多个值

“非活动InputConnection上的beginBatchEdit”,在编辑TextFormField时