【问题标题】:Show a text field dialog without being covered by keyboard?显示文本字段对话框而不被键盘覆盖?
【发布时间】:2017-10-20 02:41:00
【问题描述】:

我正在尝试创建一个SimpleDialog,允许用户输入他们的姓名。但是当它显示时,屏幕键盘将对话框隐藏了一半:

如何让Dialog 完全可见?

编辑:我觉得奇怪的是主页小部件 (FocusVisibilityDemo) 识别出降低的高度,因此调整了“Push Me”按钮的位置以保持在中心。不幸的是,对话框的行为方式不同。

这是我的代码:

import 'package:flutter/material.dart';

class FocusVisibilityDemo extends StatefulWidget {
  @override
  _FocusVisibilityDemoState createState() => new _FocusVisibilityDemoState();
}

class _FocusVisibilityDemoState extends State<FocusVisibilityDemo> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Text Dialog Demo')),
      body: new Center(
        child: new RaisedButton(
          onPressed: _showDialog,
          child: new Text("Push Me"),
        ),
      ),
    );
  }

  _showDialog() async {
    await showDialog<String>(
      context: context,
      child: new AlertDialog(
        contentPadding: const EdgeInsets.all(16.0),
        content: new Row(
          children: <Widget>[
            new Expanded(
              child: new TextField(
                autofocus: true,
                decoration: new InputDecoration(
                    labelText: 'Full Name', hintText: 'eg. John Smith'),
              ),
            )
          ],
        ),
        actions: <Widget>[
          new FlatButton(
              child: const Text('CANCEL'),
              onPressed: () {
                Navigator.pop(context);
              }),
          new FlatButton(
              child: const Text('OPEN'),
              onPressed: () {
                Navigator.pop(context);
              })
        ],
      ),
    );
  }
}

void main() {
  runApp(new MaterialApp(home: new FocusVisibilityDemo()));
}

【问题讨论】:

  • 在这种情况下,您可能需要使用全屏输入。
  • @Mark 如何获取文本字段中输入的值?
  • @ArgaPK 您应该实例化一个 TextEditingController 实例,并将其传递给您的 TextField 的“控制器”参数。然后,设置 TextField 的“onSubmitted”方法,这是一个在您点击“OK”时将被调用的方法,它有一个 String 参数 - 这是您在 TextField 中输入的数据。您还可以设置“onChanged”方法,因此每次在 TextField 中输入内容时,都会调用“onChanged”。

标签: dart flutter


【解决方案1】:

如果您的用例是在您的Dialog 中添加多个TextFields,这样您的主要Form 就不会变得拥挤,我认为如果您构建比AlertDialog 和SimpleDialog 更可定制的东西会更好它们用于简单的活动(确认、收音机等)。

否则,为什么要将Dialog 用于单个TextField?

当我们添加多个TextFields 时,我们应该小心我们的设计选择,因为其他人会与这个视图交互来填充数据,在这种情况下,我更喜欢使用PageRoute 类的fullscreenDialog 属性。我不确定SimpleDialog 是否适合在 Flutter 中使用。

这是一个关于如何使用FullScreenDialog 的简单示例,希望对您有所帮助,并且您应该能够按照自己的方式进行修改:

import 'package:flutter/material.dart';


void main() {
  runApp(new MaterialApp(home: new MyApp(),));
}

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  FullScreenDialog _myDialog = new FullScreenDialog();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Fill this form"),
        ),
        body: new Column(
          children: <Widget>[
            new TextField(controller: new TextEditingController(
                text: "Add a single text field"),),

            new Card(child: new ListTile(
              title: new Text("Click to add your top 3 amazing skills"),
              subtitle: new Text(
                  "${_myDialog._skillOne} ${_myDialog._skillTwo} ${_myDialog
                      ._skillThree}"),
              onTap: () {
                Navigator.push(context, new MaterialPageRoute(
                  builder: (BuildContext context) => _myDialog,
                  fullscreenDialog: true,
                ));
              },
            ),
            ),
          ],
        )
    );
  }

}


class FullScreenDialog extends StatefulWidget {
  String _skillOne = "You have";
  String _skillTwo = "not Added";
  String _skillThree = "any skills yet";

  @override
  FullScreenDialogState createState() => new FullScreenDialogState();
}

class FullScreenDialogState extends State<FullScreenDialog> {
  TextEditingController _skillOneController = new TextEditingController();
  TextEditingController _skillTwoController = new TextEditingController();

  TextEditingController _skillThreeController = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Add your top 3 skills"),
        ),
        body: new Padding(child: new ListView(
          children: <Widget>[
            new TextField(controller: _skillOneController,),
            new TextField(controller: _skillTwoController,),
            new TextField(controller: _skillThreeController,),
            new Row(
              children: <Widget>[
                new Expanded(child: new RaisedButton(onPressed: () {
                  widget._skillThree = _skillThreeController.text;
                  widget._skillTwo = _skillTwoController.text;
                  widget._skillOne = _skillOneController.text;
                  Navigator.pop(context);
                }, child: new Text("Save"),))
              ],
            )
          ],
        ), padding: const EdgeInsets.symmetric(horizontal: 20.0),)
    );
  }


}

编辑

经过一番研究,似乎this is a bug在当前Flutter版本中,临时修复也记录在这个问题中。

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(home: new FocusVisibilityDemo()));
}

class FocusVisibilityDemo extends StatefulWidget {
  @override
  _FocusVisibilityDemoState createState() => new _FocusVisibilityDemoState();
}


class _FocusVisibilityDemoState extends State<FocusVisibilityDemo> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Text Dialog Demo')),
      body: new Center(
        child: new RaisedButton(
          onPressed: _showDialog,
          child: new Text("Push Me"),
        ),
      ),
    );
  }

  _showDialog() async {
    await showDialog<String>(
      context: context,
      child: new _SystemPadding(child: new AlertDialog(
        contentPadding: const EdgeInsets.all(16.0),
        content: new Row(
          children: <Widget>[
            new Expanded(
              child: new TextField(
                autofocus: true,
                decoration: new InputDecoration(
                    labelText: 'Full Name', hintText: 'eg. John Smith'),
              ),
            )
          ],
        ),
        actions: <Widget>[
          new FlatButton(
              child: const Text('CANCEL'),
              onPressed: () {
                Navigator.pop(context);
              }),
          new FlatButton(
              child: const Text('OPEN'),
              onPressed: () {
                Navigator.pop(context);
              })
        ],
      ),),
    );
  }
}


class _SystemPadding extends StatelessWidget {
  final Widget child;

  _SystemPadding({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var mediaQuery = MediaQuery.of(context);
    return new AnimatedContainer(
        padding: mediaQuery.viewInsets,
        duration: const Duration(milliseconds: 300),
        child: child);
  }
}

【讨论】:

  • 不,我不想添加多个文本字段 - 我只是希望用户输入一个文本值。在我的情况下,对话框是合适的,因为它使屏幕保持清洁和最小化。让我解释一下:想象一个有两个按钮的游戏的主屏幕:“创建新游戏”和“访问共享游戏”。当用户单击第二个按钮时,应用会要求用户输入用户想要访问的游戏的唯一 ID。
  • 我的错,我发现这是一个错误,请检查答案中的编辑部分。
  • padding: mediaQuery.padding,需要改成padding: mediaQuery.viewInsets,
  • @aziza 如何获取文本字段中输入的值?
  • 要获取TextField 的值,可以使用TextEditingController。 flutter.dev/docs/cookbook/forms/retrieve-input
猜你喜欢
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 2015-05-01
  • 1970-01-01
  • 2022-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多