当我选择文本字段时,键盘会在其上移动

时间:2018-06-07 08:34:42

标签: dart flutter

当我选择文本字段时,将显示键盘,但键盘会隐藏我选择的TextField。有人有解决方案吗?

谢谢。

15 个答案:

答案 0 :(得分:5)

撰写动画并在TextField获得焦点时向上移动TextField容器。

有关撰写动画的知识,请参阅: Composing Animations and Chaining Animations in Dart's Flutter Framework

使用Flutter的FocusNode检测TextField上的焦点

修改

在这里,我写了一个完全符合你想要的例子:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Animation Demo',
      theme: new ThemeData(
        primaryColor: new Color(0xFFFF0000),
      ),
      home: new FormDemo(),
    );
  }
}

class FormDemo extends StatefulWidget {
  @override
  _FormDemoState createState() => _FormDemoState();
}

class _FormDemoState extends State<FormDemo> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  FocusNode _focusNode = FocusNode();

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

    _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
    _animation = Tween(begin: 300.0, end: 50.0).animate(_controller)
    ..addListener(() {
      setState(() {});
    });

    _focusNode.addListener(() {
      if (_focusNode.hasFocus) {
        _controller.forward();
      } else {
        _controller.reverse();
      }
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    _focusNode.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomPadding: false, // this avoids the overflow error
      appBar: AppBar(
        title: Text('TextField Animation Demo'),
      ),
      body: new InkWell( // to dismiss the keyboard when the user tabs out of the TextField
        splashColor: Colors.transparent,
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
        },
        child: Container(
          padding: const EdgeInsets.all(20.0),
          child: Column(
            children: <Widget>[
              SizedBox(height: _animation.value),
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'I move!',
                ),
                focusNode: _focusNode,
              )
            ],
          ),
        ),
      ),
    );
  }
}

答案 1 :(得分:3)

 Scaffold(
    resizeToAvoidBottomInset: true,
    body: SingleChildScrollView(
      child: Container(
        child: Column(
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            ),
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Enter Text',
              ),
            )
          ],
        ),
      ),
    )
);

// resizeToAvoidBottomPadding:不推荐使用is

使用resizeToAvoidBottomInset:正确。

答案 2 :(得分:3)

最简单的方法是将其包裹起来

SingleChildScrollView(...)

当文本字段位于页面底部并且出现键盘时,该文本字段会自动向上滚动。然后可以在键盘正上方输入文本。

答案 3 :(得分:1)

只需在此剪切并粘贴您的身体代码-

SingleChildScrollView(
            child: Stack(
              children: <Widget>[
                  // your body code 
               ],
             ),
           ),

答案 4 :(得分:1)

<activity
        android:name="..ActivityName"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize"/>

仅适用于android 如果您使用 FlutterFragment ,请为“活动”添加 configChanges windowSoftInputMode

另一种方式 将您的TextField添加到ListView

ListView(
   children: <Widget>[
     TextField(),
     TextField(),
     ]
)

答案 5 :(得分:1)

我在这里的方式

Scaffold(
    resizeToAvoidBottomInset: false,
    resizeToAvoidBottomPadding: false,
    body: Container(
      decoration: BoxDecoration(
          image: DecorationImage(
              image: AssetImage('images/Bg img.png'), fit: BoxFit.fill)),
      child: Padding(
        padding: EdgeInsets.only(
            bottom: MediaQuery.of(context).viewInsets.bottom),
        child: CustomScrollView(
          slivers: [
            SliverFillRemaining(
              hasScrollBody: false,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                .............

此模板具有一些优点:

  • 出现键盘时上移内容
  • 在滚动视图内使用spaceBetween的列
  • 背景始终不停地拨动电话,并且永远不会更改键盘ups

答案 6 :(得分:0)

不需要手动处理动画。只需用SingleChildScrollView包裹文本字段即可:

SingleChildScrollView(
  child: Column(
    children: <Widget>[
      TextField(),
      TextField(),
      TextField(),
      TextField(),
      TextField()
  ]
)
Flutter中的

SingleChildScrollView与iOS中的TPKeyboardAvoiding一样

答案 7 :(得分:0)

一个很短的实​​现方法是通过使用MediaQuery获取底视图插图。如下所示:

...
return Row(
  children: <Widget>[
    TextField(
      decoration: InputDecoration.collapsed(hintText: "Start typing ..."),
      controller: _chatController,
    ),
    SizedBox(
      height: MediaQuery.of(Context).viewInsets.bottom,
    ),
  ],
);
...

希望有帮助!

答案 8 :(得分:0)

如果您在CustomScrollview中有NestedScrollView,以上操作将无效。

  1. 首先,您需要为TextField提供一个focusNode。

    TextField(focusNode:_focusNode(),
      ...);
    
  2. 使用NestedScrollViewState来访问innerScrollController中的NestedScrollView。您可以查看有关如何获取innerScrollController的示例here。声明一个globalKey并将其分配给NestedScrollView。

     body: NestedScrollView(
        key: globalKey,
        ...)
    
  3. 设置focusNode侦听器以侦听何时激活了文本字段,并相应地为innerScrollController设置动画。

    void initState() {
      super.initState();

      _focusNode.addListener(() {
        if (_focusNode.hasFocus) {

          double innerOffSet = globalKey.currentState.innerController.offset;
          if(innerOffSet < 100)
            globalKey.currentState.innerController.jumpTo(innerOffSet+100);
      }

    });


  }

答案 9 :(得分:0)

var _contentController;

void _settingModalBottomSheet(BuildContext context, String initialText) {
   _contentController = new TextEditingController(text: initialText);
    showModalBottomSheet(
        context: context,
        isDismissible: true,
        builder: (BuildContext bc) {
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Container(
                height: 40,
                margin: EdgeInsets.only(left: 4, right: 4, bottom: 8),
                decoration: BoxDecoration(
                  color: AppColor.bgTextFieldComment,
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Row(
                  children: <Widget>[
                    Expanded(
                      child: Padding(
                          padding: EdgeInsets.only(left: 24),
                          child: TextField(
                            focusNode: _contentFocusNode,
                            autofocus: true,
                            controller: _contentController,
                            decoration: InputDecoration(
                              hintText: 'Enter Content',
                              border: InputBorder.none,
                              fillColor: AppColor.bgTextFieldComment,
                            ),
                            keyboardType: TextInputType.multiline,
                            maxLines: null,
                            style: TextStyle(
                              color: Colors.black87,
                              fontSize: 16,
                              fontStyle: FontStyle.normal,
                            ),
                          )),
                    ),
                    InkWell(
                      child: Padding(
                        padding: EdgeInsets.only(left: 4, right: 4),
                        child: Icon(
                          Icons.send,
                          color: Colors.blue,
                        ),
                      ),
                      onTap: () {
                          // do ON TAP
                      },
                    ),
                  ],
                ),
              ),
              SizedBox(
                height: MediaQuery.of(bc).viewInsets.bottom,
              ),
            ],
          );
        },).then((value) {
      print('Exit Modal');
    });
    print('request focus');
    _contentFocusNode.requestFocus();
  }

答案 10 :(得分:0)

在我的情况下,我必须结合使用@Javid Noutash的{​​{1}}和AnimationController的{​​{1}}属性给出的答案。 代码:

在构建方法中添加此行

scrollPadding

添加TextFormField属性

double bottomInsets = MediaQuery.of(context).viewInsets.bottom;

注意:将此代码与scrollPadding的代码合并

答案 11 :(得分:0)

使用 TextField 代替 TextFormField,并使用 TextFormFieldForm 的列表包装小部件:

Form(
  child: Column(
    children: <Widget> [
      TextFormField(),
      TextFormField(),
        ...
      TextFormField(),
    ]
  )
)

答案 12 :(得分:0)

我遇到了同样的问题,其中父小部件是 Material,其他小部件在 ListView 内。当我在没有任何额外代码的情况下将父小部件更改为 Scaffold 并且 TextField(在我的情况下为 TextFormField)自动显示在键盘上方时,问题得到了解决。因此,如果您遇到此问题,只需确保将 Scaffold 作为主要小部件1

答案 13 :(得分:0)

你可以很容易地尝试使用灵活的小部件,只需用它包裹你的小部件


Flexible(
            child: Image(
              image :
            AssetImage('assets/logo.png'),

            ),
          ),

答案 14 :(得分:-3)

就我而言,检查代码很容易

         Column(
          children: [
            Expanded(
              child:// Top View,
            ),
            postSend // edittext. and button 
          ],
        )