Home > other >  How to animate Align without using AnimatedAlign and control the animation
How to animate Align without using AnimatedAlign and control the animation

Time:07-31

I am trying to achieve a pretty simple animation in Flutter but I am stuck.

The current animation looks like this (iPhone Screen recording): https://drive.google.com/file/d/10pzUadQrSr85eLLpyh7v3lt-x8XjFNec/view?usp=sharing

I am currently doing this with Positioned but I can not do it precisely as I want. Is there any chance that I can do this animation with Align Widget.

I have tried using AnimatedAlign and Tweens but none of them allow me to modify the Images position by scrolling up or down on the bottom sheet.

The Code:

late AnimationController bottomSheetController;

double bsOffset = 1;

@override
void initState() {
  super.initState();
  bottomSheetController = BottomSheet.createAnimationController(this);
  bottomSheetController.duration = Duration(milliseconds: 200);

  bottomSheetController.addListener(() {
    double size = (bottomSheetController.value.toDouble() - 1) * -1;

    setState(() {
      if (size != 0) {
        bsOffset = size;
      }
    });
  });
}
.
.
.
void _handleFABPressed() {
  showModalBottomSheet(
    backgroundColor: Colors.transparent,
    barrierColor: Colors.transparent,
    transitionAnimationController: bottomSheetController,
    context: context,
    builder: (context) {
      return Popover(
        child: Container(
          height: 400,
          // color: Colors.lightBlue,
        ),
      );
    },
  );
}
.
.
.
child: Stack(
  alignment: Alignment.topCenter,
  children: [
    Positioned(
      bottom: 50 - (50 * bsOffset),
      left: ((200 / 2) - 20) - (((200 / 2) - 20) * (bsOffset - 1) * -1),
      child: Image.asset(
        'assets/images/8.png',
        width: 200,
      ),
    ),
  ],
),

Thank You!

CodePudding user response:

If I were to move the two widgets, both Align and the bottomsheet, I would do it like this:

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

  class MyApp extends StatelessWidget {
    const MyApp({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const MyHomePage(),
      );
    }
  }

  class MyHomePage extends StatefulWidget {
    const MyHomePage({Key? key}) : super(key: key);

    @override
    State<MyHomePage> createState() => _MyHomePageState();
  }

  class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
    late AnimationController _animationController;
    late Animation<Offset> _animationOffset;
    var _alignment = Alignment.bottomCenter;

    void _show() {
      showModalBottomSheet(
          backgroundColor: Colors.transparent,
          barrierColor: Colors.transparent,
          transitionAnimationController: _animationController,
          context: context,
          builder: (context) {
            return Container(
              height: 400,
              color: Colors.red,
            );
          });
    }

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo Home Page'),
        ),
        body: Stack(
          children: [
            Align(
                alignment: _alignment,
                child: const SizedBox(
                    width: 100, height: 100, child: Card(color: Colors.red)))
          ],
        ),
        floatingActionButton:
            FloatingActionButton(onPressed: _show, child: const Icon(Icons.add)),
      );
    }

    void _onListenerAnimation() {
      setState(() {
        _alignment =
            Alignment(_animationOffset.value.dx, _animationOffset.value.dy);
      });
    }

    @override
    void initState() {
      super.initState();
      _animationController = AnimationController(
          vsync: this, duration: const Duration(milliseconds: 200))
        ..addListener(_onListenerAnimation);

      _animationOffset = Tween<Offset>(
        begin: const Offset(0, 1),
        end: const Offset(-1, -0.6),
      ).animate(_animationController);
    }

    @override
    void dispose() {
      super.dispose();
      _animationController
        ..removeListener(_onListenerAnimation)
        ..dispose();
    }
  }
  • Related