Home > Software engineering >  Transition from large to small image smooth animation - Flutter
Transition from large to small image smooth animation - Flutter

Time:10-21

I have a login-page where I want the transition of the logo from large to small (and back) to be smoother. As it is now, it just pops between the two.

When the keyboard opens, I would like the logo to animate to the smaller position, instead of just instantly changing.

Does anyone know a way to do this?

@override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
      resizeToAvoidBottomInset: true,
      backgroundColor: AppColors.yellowLight,
      // appBar: MainAppBar(),
      body: SingleChildScrollView(
        physics: BouncingScrollPhysics(),
          child: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Container(
                  padding: EdgeInsets.symmetric(vertical: 90),
                  child: Image(
                    image: ExactAssetImage('assets/icons/app_logo.png'),
                    height: MediaQuery.of(context).viewInsets.bottom == 0
                        ? size.height * 0.3
                        : size.height * 0.15,
                    fit: BoxFit.fitHeight,
                    alignment: Alignment.center,
                  ),
                ),
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 50),
                  child: MainTextField(
                      controller: emailController,
                      labelText: 'E-post',
                      hintText: 'Skriv e-post som [email protected]'),
                ),
                Padding(
                  padding: const EdgeInsets.only(
                      left: 50.0, right: 50.0, top: 30, bottom: 30),
                  child: MainTextField(
                    controller: passwordController,
                    obscureText: true,
                    labelText: 'Passord',
                    hintText: 'Skriv inn sikkert passord',
                  ),
                ),
                LoginButton(
                  text: 'Logg inn',
                  isLoading: isLoading,
                  onPressed: _login,
                ),
                // Text('New User? Create Account')
              ],
            ),
          ),
        ),
    );
  }

CodePudding user response:

 AnimatedContainer(
              height: MediaQuery.of(context).viewInsets.bottom != 0 ? 100.0 : 200.0,
              width: MediaQuery.of(context).viewInsets.bottom != 0 ? 100 : 200.0,
              duration:const Duration(milliseconds: 750),
              curve: Curves.fastOutSlowIn,
              child: Image.network("https://picsum.photos/200/300"),
            ),

but MediaQuery.of(context).viewInsets.bottom it won't give you accuracy as if it's real time when changing the keyboard state, so I advice you to use another method to know the current state of the keyboard like the code below

enter image description here

you can use this package to listen for keyboard change flutter_keyboard_visibility here is the code

class _MyHomePageState extends State<MyHomePage> {
  late StreamSubscription<bool> keyboardSubscription;

  bool _isVisible = false;

  @override
  void initState() {
    super.initState();
    var keyboardVisibilityController = KeyboardVisibilityController();
    // Subscribe
    keyboardSubscription = keyboardVisibilityController.onChange.listen((bool visible) {
      if(mounted) {
        setState(() {
          _isVisible = visible;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedContainer(
              height: _isVisible ? 100.0 : 200.0,
              width: _isVisible ? 100 : 200.0,
              duration:const Duration(milliseconds: 750),
              curve: Curves.fastOutSlowIn,
              child: Image.network("https://picsum.photos/200/300"),
            ),
            Spacer(),
            const Text(
              'You have pushed the button this many times:',
            ),


            TextFormField(

            ),
            Spacer(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){},
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  @override
  void dispose() {
    keyboardSubscription.cancel();
    super.dispose();
  }
}

if you don't want to use package for keyboard visibility so you can use this code

class _MyHomePageState extends State<MyHomePage> {
 final FocusNode _myNode =  FocusNode();

  bool _isVisible = false;

  @override
  void initState() {
    super.initState();
  _myNode.addListener(_listener);
  }

  void _listener(){
    if(_myNode.hasFocus){
      // keyboard appeared
      if(mounted){
        setState(() {
          _isVisible = true;
        });
      }
    }else{
      // keyboard dismissed
      if(mounted){
        setState(() {
          _isVisible = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedContainer(
              height: _isVisible ? 100.0 : 200.0,
              width: _isVisible ? 100 : 200.0,
              duration:const Duration(milliseconds: 750),
              curve: Curves.fastOutSlowIn,
              child: Image.network("https://picsum.photos/200/300"),
            ),
            Spacer(),
            const Text(
              'You have pushed the button this many times:',
            ),


            TextFormField(
              focusNode: _myNode,

            ),
            Spacer(),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){},
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  @override
  void dispose() {
    _myNode.removeListener(_listener);
    super.dispose();
  }
}

CodePudding user response:

I found a way that kind of works. At least the animation does. But as it is based on MediaQuery.of(context).viewInsets.bottom == 0 still, the animation does not start until the keyboard is all the way out of view.

            AnimatedContainer(
            duration: Duration(milliseconds: 400),
            curve: Curves.fastOutSlowIn,
            padding: MediaQuery.of(context).viewInsets.bottom == 0
                ? EdgeInsets.symmetric(vertical: 100)
                : EdgeInsets.only(top: 75, bottom: 10),
            height: MediaQuery.of(context).viewInsets.bottom == 0
                ? _height.height * 0.5
                : _height.height * 0.25,
                child: Image(
              image: ExactAssetImage('assets/icons/app_logo.png'),
            ),
          ),
  • Related