当TextField或TextFormField获取焦点时,在Flutter中将屏幕底部推到键盘之上

7

我希望实现这样的布局,只有主要按钮部件始终位于底层。其它部件将放置在SingleChildScrollView->Column中。

但是当焦点在TextFieldTextFormField中时,键盘应将全屏向下推,直到底部布局可见按钮。

仅使用SingleChildScrollView仅使TextFieldTextFormField位于键盘上方,而不包括按钮。

我的代码:

body: SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          child: Container(
            height: screenHeight(context) - kToolbarHeight - 24,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                PlaceHolder(),
                SizedBox(height: 20.0),
                Text('Select Time'),
                SizedBox(height: 10.0),
                PlaceHolder(),
                SizedBox(height: 20.0),
                PlaceHolder(),
                SizedBox(height: 20.0),
                // InputField is a TextFormField
                InputField(
                  controller: _dataController,
                  labelText: 'Enter Data',
                  fieldFocusNode: _dataFocusNode,
                  textInputType: TextInputType.text,
                ),
                SizedBox(height: 20.0),
                CheckboxListTile(),
                SizedBox(height: 20.0),
                PrimaryButton(
                  buttonText: 'Save',
                  onPressed: () {},
                ),
                SizedBox(height: 20.0),
              ],
            ),
          ),
        ),

以下是两个屏幕布局。您可以忽略除了TextFormFieldMain Button之外的所有其他小部件。

屏幕一:没有键盘(TextFieldTextFormField未聚焦)

屏幕一:没有键盘(TextField或TextFormField未聚焦)

屏幕二:有键盘(TextFieldTextFormField已聚焦)

屏幕二:有键盘(TextField或TextFormField已聚焦)

2个回答

14
请按照以下步骤操作:
1. 删除高度固定的 Container
2. 在页面底部添加一个 Padding 组件,并将其 bottom 属性设置为 MediaQuery.of(context).viewInsets.bottom
3. 将 SingleChildScrollView 的属性设置为 reverse: true
4. 将 Scaffold 的属性设置为 resizeToAvoidBottomInset: false
5. 将 Scaffold 的属性设置为 resizeToAvoidBottomPadding: false
完整代码(更改用注释标记):
return Scaffold(
      resizeToAvoidBottomInset: false, // this is new
      resizeToAvoidBottomPadding: false, // this is new
      body: SingleChildScrollView( 
        reverse: true, // this is new 
        physics: BouncingScrollPhysics(),
        child: Column( // the container is removed
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            PlaceHolder(),
            SizedBox(height: 20.0),
            Text('Select Time'),
            SizedBox(height: 10.0),
            PlaceHolder(),
            SizedBox(height: 20.0),
            PlaceHolder(),
            SizedBox(height: 20.0),
            // InputField is a TextFormField
            InputField(
              controller: _dataController,
              labelText: 'Enter Data',
              fieldFocusNode: _dataFocusNode,
              textInputType: TextInputType.text,
            ),
            SizedBox(height: 20.0),
            CheckboxListTile(),
            SizedBox(height: 20.0),
            PrimaryButton(
              buttonText: 'Save',
              onPressed: null, // changed this since it had a syntax error
            ),
            Padding( // this is new
                padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
            ),
          ],
        ),
      ),
    );

你是一个天才。+1。 它即使今天也可以工作。 - Harmeet Singh

0
SingleChildScrollView 包裹你的屏幕。

只有将文本框保持在键盘上方,而不是按钮。 - user7962929
如果您从容器中删除高度,它会起作用吗@AbdullahAlNahid? - HBS
其中一个占位符小部件是GridView,需要指定高度。容器高度可以帮助解决这个问题。如果没有容器高度,Column中的GridView会崩溃。 - user7962929
使用Expanded将GridView包装起来,并移除高度限制。 - HBS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接