martinrybak / keyboard_avoider

A lightweight alternative to the Scaffold widget for avoiding the on-screen software keyboard. Automatically scrolls obscured TextField child widgets into view on focus.
https://medium.com/flutter-nyc/avoiding-the-on-screen-keyboard-in-flutter-ae0e46ecb96c
MIT License
118 stars 41 forks source link

Avoid unnecessary overlap #7

Open sasanrose opened 4 years ago

sasanrose commented 4 years ago

This patch tries to fix a problem where the didChangeMetrics is called when the phone is unlocked and then _resize makes wrong calculations and assumptions that the keyboard is now visible. The details of the bug are really hard to explain. So I thought a sample code and some screencasts can do better than writing. Please take a look at the following sample:

import 'package:flutter/material.dart';
import 'package:keyboard_avoider/keyboard_avoider.dart';

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

class MyApp extends StatefulWidget {
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  bool _offstage;
  @override
  void initState() {
    _offstage = true;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        floatingActionButton: FloatingActionButton(
            onPressed: () {
              setState(() {
                _offstage = !_offstage;
              });
            },
            child: Icon(_offstage ? Icons.arrow_left : Icons.arrow_right)),
        body: _body(),
      ),
    );
  }

  Widget _body() {
    return Stack(
      children: <Widget>[
        Container(
          child: Offstage(
              offstage: _offstage,
              child: AnimatedContainer(
                duration: Duration(milliseconds: 800),
                curve: Curves.fastLinearToSlowEaseIn,
                transform: Matrix4.identity()..translate(50.0),
                child: Row(
                  children: <Widget>[
                    Column(children: [
                      Flexible(
                        child: _buildPlaceholder(Colors.red),
                      )
                    ])
                  ],
                ),
              )),
        ),
        AnimatedContainer(
          duration: Duration(microseconds: 800),
          curve: Curves.fastLinearToSlowEaseIn,
          transform: Matrix4.identity()
            ..translate(_offstage ? 0.0 : -365.0, _offstage ? 0.0 : 44.0)
            ..scale(_offstage ? 1.0 : 0.9),
          child: Row(
            children: <Widget>[
              Flexible(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Flexible(
                      flex: 1,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Material(
                              child: TextField(
                            decoration: InputDecoration(
                                border: OutlineInputBorder(
                                    borderRadius:
                                        BorderRadius.all(Radius.circular(25)))),
                            maxLines: 1,
                          )),
                        ],
                      ),
                    ),
                    Flexible(
                        flex: 4, child: _buildPlaceholder(Colors.lightBlue)),
                  ],
                ),
              ),
            ],
          ),
        )
      ],
    );
  }

  Widget _buildPlaceholder(Color color) {
    return Container(
      color: color,
      child: KeyboardAvoider(
        child: Placeholder(),
      ),
    );
  }
}

Before the patch

before-opt

After the patch

after-opt