36

I'm building a Flutter app, mainly for iOS.

One of my views has a text field, and iOS keyboard appears when you tap on it. The problem is - layout does not change smoothly like it does in native iOS apps. Instead, it instantly jumps to the final available screen height even before keyboard opening animation finishes.

I tried wrapping my SafeArea element in AnimatedSize and AnimatedContainer - it didn't help.

My layout code:

SafeArea(child:
  Column(children:[
    TextField(...)
  ])
)

How can I make the layout resize smoothly when the keyboard appears?

Expected:

how I expect it to be.gif

Actual

how it is - laggy resizing in Flutter app.gif

8
  • 1
    Can you update your question with a gif/screenshot? Commented Feb 7, 2019 at 1:51
  • @miguelpruivo attached gifs. The difference is not so noticeable due to low FPS rate, but I hope it's clear what I'm trying to achieve - smooth resizing of SafeArea when keyboard appears. Commented Feb 7, 2019 at 19:18
  • Have you tried to wrap your input field only, in an AnimatedContainer? You may want to edit your question with some code. What's happening is that when you launch the keyboard, the viewInsets from the bottom are being used by the keyboard and the view is being rebuilt to match the changes but not actually animating along with it. That's a good question though. Commented Feb 8, 2019 at 10:11
  • Is this possible due to debug mode? Try to release apk or use --profile Commented Mar 12, 2019 at 10:21
  • 2
    you can check this issue on github https://github.com/flutter/flutter/issues/19279 this might help Commented May 4, 2020 at 7:59

5 Answers 5

8

I use something like that:

AnimatedPadding(
        padding: MediaQuery.of(context).viewInsets,
        duration: const Duration(milliseconds: 100),
        curve: Curves.decelerate,
        child: ....
    )

This animates the padding based on the viewInsets(software keyboard height).

Sign up to request clarification or add additional context in comments.

1 Comment

While this code may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion
6

The desired output can be achieved using AnimatedPadding Widget, though this is not perfect, but better than nothing :d

Open issue as of 15/03/21, for reference

import 'dart:math';

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      bottom: false,
      child: Scaffold(
          // !!! Important part > to disable default scaffold insets
          resizeToAvoidBottomInset: false,
          appBar: AppBar(
            title: Text("Appbar Title"),
          ),
          body: Stack(
            children: [
              Scrollbar(
                child: ListView.builder(
                  padding: EdgeInsets.all(0.0),
                  itemCount: 30,
                  itemBuilder: (context, i) {
                    return Container(
                      height: 100,
                      width: double.infinity,
                      color: Colors
                          .primaries[Random().nextInt(Colors.primaries.length)],
                    );
                  },
                ),
              ),
              Align(
                alignment: Alignment.bottomLeft,
                child: AnimatedPadding(
                    padding: MediaQuery.of(context).viewInsets,
                    // You can change the duration and curve as per your requirement:
                    duration: const Duration(milliseconds: 200),
                    curve: Curves.decelerate,
                    child: InputField()),
              )
            ],
          )),
    );
  }
}

class InputField extends StatefulWidget {
  InputField({Key key}) : super(key: key);

  @override
  _InputFieldState createState() => _InputFieldState();
}

class _InputFieldState extends State<InputField> {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey[100],
      padding: const EdgeInsets.symmetric(vertical: 6),
      child: Row(
        children: [
          SizedBox(
            width: 60,
            child: Icon(Icons.add_a_photo),
          ),
          Flexible(
            child: TextField(
              style: Theme.of(context).textTheme.bodyText1,
              decoration: InputDecoration(
                border: InputBorder.none,
                hintText: 'Enter text...',
              ),
            ),
          ),
          SizedBox(
            width: 60,
            child: Icon(Icons.send),
          ),
        ],
      ),
    );
  }
}

Output -> enter image description here

Comments

0

You can use this package keyboard_visibility and listen to keyboard visibility. Then you can give your logic to implement your feature like you can shorten the home container height. That's not perfect . But I think it's the only way right now.

Comments

0

You need to use keyboard_visibility package and use it to trigger your AnimatedContainer or AnimatedPadding

bool _isKeyboardActive = false;
@override
void initState() {
  super.initState();
  //add keyboard visibility Listener
  KeyboardVisibility.onChange.listen((event) {
    setState(() {
      _isKeyboardActive = event;
    });
  });
}


Widget build(BuildContext context){
    return AnimatedContainer(
       width: _isKeyboardActive ? 200 : MediaQuery.of(context).size.width,
       height: 60,
       color: Colors.red,
       duration: Duration(milliseconds: 600)
    )
}

use this as a basis.

Comments

-8

You should try setting resizeToAvoidBottomPadding: false like so:

return Scaffold(
      key: _scaffoldKey,
      resizeToAvoidBottomPadding: false,

1 Comment

please dont put a random answers , reading the question and understand it before gave an answers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.