Anton Schrage
Anton Schrage

Reputation: 1301

When I select a Textfield the keyboard moves over it

When i select a Textfield, the keyboard is going to be shown but the keyboard hide my selected TextField. Does someone have a solution?

Upvotes: 41

Views: 87400

Answers (17)

Lucas Aschenbach
Lucas Aschenbach

Reputation: 960

A pretty short way to realize this is by simply using a MediaQuery for getting the bottom view insets. This would look as follows:

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

Hope it helps!

Upvotes: 25

Exceptional
Exceptional

Reputation: 3004

Wrap with MaterialApp, it should work.

 @override
  Widget build(BuildContext context) {
    buildContext = context;
    return ScreenUtilInit(
      designSize: getDeviceSize(context),
      splitScreenMode: true,
      builder: (BuildContext buildContext, Widget? child) {
        return MaterialApp(
          theme: Styles.appTheme(),
          home: Container(
            decoration: const BoxDecoration(
              color: AppColors.backgroundColor,
            ),

Upvotes: 0

Miro
Miro

Reputation: 449

I had a very complex widget with Stack, Column and Single ChildChildScrollView, and I fixed it by adding a padding to the SCSV like this:

child: Stack(
  children: [
    Padding(
      padding: const EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
      child: SingleChildScrollView(
        child: Column(
          children: [... a lot of children here, one of them is a TextField],
        ),
      ),
    ),
    // a widget at the bottom of the stack that shows despite the size of the scrollable column
  ],
),

Upvotes: 5

Kien Vu
Kien Vu

Reputation: 1048

Wrap your widget into Padding and set padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),

Upvotes: 5

Ziyad Shoeky
Ziyad Shoeky

Reputation: 31

you can easily try to use Flexible widget just wrap your widget with it


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

            ),
          ),

Upvotes: 0

Hitesh sapra
Hitesh sapra

Reputation: 256

It's very easy in my case check out code

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

Upvotes: -3

Abdul Razak Zakieh
Abdul Razak Zakieh

Reputation: 764

I had the same problem where the parent widget is Material and the other widgets are inside a ListView. The problem was fixed when I changed the parent widget to Scaffold without any extra code and the TextField, TextFormField in my case, is being showed above the Keyboard automatically. So, if you encountered this problem just make sure to have Scaffold as the main widget. 1

Upvotes: 6

Firosh Vasudevan
Firosh Vasudevan

Reputation: 801

In my case I had to combine answer given by @Javid Noutash which uses AnimationController along with scrollPadding property of TextFormField. code:

Add this line in build method

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

Add scrollPadding property

return ListView(
children:[

...widgets,
Container(
margin:EdgeInsets.only(
   top:1.0,
   left:1.0,
   right:1.0,
   bottom:_focusNode.hasFocus && bottomInsets != 0?
          _animation.value : 1.0),
child:TextFormField(
   decoration: InputDecoration(
                  labelText: 'I move!',
               ),
   focusNode: _focusNode,
   scrollPadding: EdgeInsets.only(bottom:bottomInsets + 40.0),
  ),
 ),
]
);

Note: Combine this code with @Javid Noutash's code

Upvotes: 8

Mr. HAshford
Mr. HAshford

Reputation: 1

Instead of TextField, use TextFormField and wrap the widget with a list of TextFormField to Form:

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

Upvotes: 0

O Thạnh Ldt
O Thạnh Ldt

Reputation: 1223

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();
  }

Upvotes: 0

karmelcorn
karmelcorn

Reputation: 597

The above does not work if you have a CustomScrollview in a NestedScrollView.

  1. First, you need to give the TextField a focusNode.

    TextField(focusNode:_focusNode(),
      ...);
    
  2. Use NestedScrollViewState to get access to the innerScrollController of the NestedScrollView. You can view the example here on how to get the innerScrollController. Declare a globalKey and assign it to NestedScrollView.

     body: NestedScrollView(
        key: globalKey,
        ...)
    
  3. Setup the focusNode Listener to listen for when the textfield has been activated and animate the innerScrollController accordingly.

    void initState() {
      super.initState();

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

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

    });


  }

Upvotes: 0

Quinto
Quinto

Reputation: 51

My way here

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: [
                .............

This template has some advantages:

  • Move content up when the keyboard appears
  • Column using spaceBetween inside a scroll view
  • Background is sticked phone scren and never change event the keyboard ups

Upvotes: 3

Christian Dressler
Christian Dressler

Reputation: 166

The most simple way is to just wrap it with

SingleChildScrollView( ... )

When the textfield is on the page bottom and the keyboard appears, the textfield is automatically scrolled up. Then the text may be entered right above the keyboard.

Upvotes: 3

Ankush Modi
Ankush Modi

Reputation: 484

 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: false isDeprecated

use resizeToAvoidBottomInset: true.

Upvotes: 40

Karzan Kamal
Karzan Kamal

Reputation: 1242

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

only for android if you use FlutterFragment add configChanges and windowSoftInputMode for the Activity.

another way add your TextField to a ListView

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

Upvotes: 1

Harsh Kashyap
Harsh Kashyap

Reputation: 256

Just cut and paste your body code in this -

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

Upvotes: 19

Javid Noutash
Javid Noutash

Reputation: 2252

Compose an animation and move your TextField container up when a TextField gets focus.

For learning about composing animations refer to: Composing Animations and Chaining Animations in Dart's Flutter Framework

Use Flutter's FocusNode to detect the focus on a TextField

Edit:

Here I've written an example that does exactly what you want:

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,
              )
            ],
          ),
        ),
      ),
    );
  }
}

Upvotes: 31

Related Questions