Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate Flutter layout on keyboard appearance

Tags:

ios

flutter

dart

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

like image 982
George Avatar asked Feb 06 '19 22:02

George


2 Answers

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).

like image 181
YoBo Avatar answered Sep 21 '22 15:09

YoBo


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

like image 39
Kapil Sahu Avatar answered Sep 17 '22 15:09

Kapil Sahu