Flutter 创建类似 Headspace 应用程序的动画

问题描述 投票:0回答:1

想在flutter中实现类似Headspace app的动画。

flutter flutter-animation
1个回答
0
投票

结果

代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: HeadspaceWidget(),
        ),
      ),
    );
  }
}

class HeadspaceWidget extends StatefulWidget {
  @override
  _HeadspaceWidgetState createState() => _HeadspaceWidgetState();
}

class _HeadspaceWidgetState extends State<HeadspaceWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _circleSizeAnimation;
  late Animation<double> _circleMovementAnimation;
  late Animation<double> _textMovementAnimation;
  late Animation<double> _textOpacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 1),
      vsync: this,
    );

    _circleSizeAnimation = Tween<double>(begin: 200.0, end: 50.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.0,
          0.5, // Halfway through the animation
          curve: Curves.easeOut,
        ),
      ),
    );

    _circleMovementAnimation = Tween<double>(begin: 0.0, end: -20.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.5,
          1.0,
          curve: Curves.easeInOut,
        ),
      ),
    );

    _textMovementAnimation = Tween<double>(begin: 15, end: 20.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.5,
          1.0,
          curve: Curves.easeInOut,
        ),
      ),
    );

    _textOpacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.5, // Start fading in the text after the circle finishes shrinking
          1.0,
          curve: Curves.easeIn,
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              children: [
                ElevatedButton(
                  onPressed: () {
                    _controller.forward();
                  },
                  child: Text('Start Animation'),
                ),
                ElevatedButton(
                  onPressed: () {
                    _controller.reverse();
                  },
                  child: Text('Reverse Animation'),
                ),
              ],
            ),
            SizedBox(height: 20),
            Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Center(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Transform.translate(
                        offset: Offset(_circleMovementAnimation.value + 20, 0),
                        child: Container(
                          width: _circleSizeAnimation.value,
                          height: _circleSizeAnimation.value,
                          decoration: BoxDecoration(
                            color: Colors.orange,
                            shape: BoxShape.circle,
                          ),
                        ),
                      ),
                      Transform.translate(
                        offset: Offset(_textMovementAnimation.value, 0),
                        child: AnimatedOpacity(
                          opacity: _textOpacityAnimation.value,
                          duration: Duration
                              .zero,
                          child: Text(
                            'headspace',
                            style: TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ],
        );
      },
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.