flutterdartanimationslide

Slide Animation in flutter is not working as expected


I have a widget placed in a stack widget. i want to animate it from bottom right to bottom centre. but whatever i do, it doesnt work. below is the code

import 'package:flutter/material.dart';

class ToastPage extends StatefulWidget {
  const ToastPage({super.key});

  @override
  State<ToastPage> createState() => _ToastPageState();
}

class _ToastPageState extends State<ToastPage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _animation;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 1));
    _animation =
        Tween<Offset>(begin: const Offset(1, 1), end: const Offset(0, 1))
            .animate(_controller);
    super.initState();
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Stack(
          children: [
            MaterialButton(
              onPressed: () {
                _controller.reset();
                _controller.forward();
              },
              child: const Text("Animate"),
            ),
            Positioned(
              right: 10,
              bottom: 80,
              left: 0,
              child: Row(
                children: [
                  SlideTransition(
                    position: _animation,
                    child: Container(
                      height: 70,
                      width: 200,
                      color: Colors.green,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Ive tried with giving full width to the widget which is working. but the whole area is covering in green color. i actually want a box with width 200 and height 70 to animate. any help will be appreciated


Solution

  • The issue is your 70x200 container is in the Row and it will be left-aligned, so it will animate from center to left. To make it animate from right to center is quite simple, just change your Row inside the Positioned widget to the UnconstrainedBox widget, so it will unconstraint the parent layout, and use the constraint size from the container (70x200)

    This is the result:

    demo

    The final code is below.

    *The change that I mentioned above marked with comment.

    class ToastPage extends StatefulWidget {
      const ToastPage({super.key});
    
      @override
      State<ToastPage> createState() => _ToastPageState();
    }
    
    class _ToastPageState extends State<ToastPage>
        with SingleTickerProviderStateMixin {
      late AnimationController _controller;
      late Animation<Offset> _animation;
    
      @override
      void initState() {
        _controller =
            AnimationController(vsync: this, duration: const Duration(seconds: 1));
        _animation =
            Tween<Offset>(begin: const Offset(1, 1), end: const Offset(0, 1))
                .animate(_controller);
        super.initState();
        _controller.forward();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SizedBox(
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
            child: Stack(
              children: [
                MaterialButton(
                  onPressed: () {
                    _controller.reset();
                    _controller.forward();
                  },
                  child: const Text("Animate"),
                ),
                Positioned(
                  right: 10,
                  bottom: 80,
                  left: 0,
                  child: UnconstrainedBox( // <----- Change from row to this
                    child: SlideTransition(
                      position: _animation,
                      child: Container(
                        height: 70,
                        width: 200,
                        color: Colors.green,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    Hopefully it can solve your problem 😉