Flutter - Effect of flip card

后端 未结 3 931
忘掉有多难
忘掉有多难 2020-12-28 11:26

I\'m trying to make a flip card, what would be the best way to get the effect

相关标签:
3条回答
  • 2020-12-28 11:48

    You can use the flip_card Flutter package. It lets you define a front and back widget and can be flipped horizontally or vertically.

    0 讨论(0)
  • 2020-12-28 12:04

    I used simple approach, rotated it on X axis. Here is the full code.

    void main() => runApp(MaterialApp(home: HomePage()));
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
      AnimationController _controller;
      bool _flag = true;
      Color _color = Colors.blue;
    
      @override
      void initState() {
        super.initState();
        _controller = AnimationController(vsync: this, duration: Duration(seconds: 1), value: 1);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.crop_rotate),
            onPressed: () async {
              if (_flag) {
                await _controller.reverse();
                setState(() {
                  _color = Colors.orange;
                });
                await _controller.forward();
              } else {
                await _controller.reverse();
                setState(() {
                  _color = Colors.blue;
                });
                await _controller.forward();
              }
    
              _flag = !_flag;
            },
          ),
          body: Center(
            child: AnimatedBuilder(
              animation: _controller,
              builder: (context, child) {
                return Transform(
                  transform: Matrix4.rotationX((1 - _controller.value) * math.pi / 2),
                  alignment: Alignment.center,
                  child: Container(
                    height: 100,
                    margin: EdgeInsets.symmetric(horizontal: 20),
                    padding: EdgeInsets.symmetric(vertical: 12),
                    alignment: Alignment.center,
                    decoration: BoxDecoration(color: _color.withOpacity(0.2), border: Border.all(color: Colors.grey)),
                    child: FlutterLogo(colors: _color, size: double.maxFinite),
                  ),
                );
              },
            ),
          ),
        );
      }
    }
    
    0 讨论(0)
  • 2020-12-28 12:08

    I would use an AnimatedBuilder or AnimatedWidget to animate the values of a Transform widget. ScaleTransition almost does this for you, but it scales both directions, and you only want one.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          home: new MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePageState createState() => new MyHomePageState();
    }
    
    class MyCustomCard extends StatelessWidget {
      MyCustomCard({ this.colors });
    
      final MaterialColor colors;
    
      Widget build(BuildContext context) {
        return new Container(
          alignment: FractionalOffset.center,
          height: 144.0,
          width: 360.0,
          decoration: new BoxDecoration(
            color: colors.shade50,
            border: new Border.all(color: new Color(0xFF9E9E9E)),
          ),
          child: new FlutterLogo(size: 100.0, colors: colors),
        );
      }
    }
    
    class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      AnimationController _controller;
      Animation<double> _frontScale;
      Animation<double> _backScale;
    
      @override
      void initState() {
        super.initState();
        _controller = new AnimationController(
          vsync: this,
          duration: const Duration(seconds: 1),
        );
        _frontScale = new Tween(
          begin: 1.0,
          end: 0.0,
        ).animate(new CurvedAnimation(
          parent: _controller,
          curve: new Interval(0.0, 0.5, curve: Curves.easeIn),
        ));
        _backScale = new CurvedAnimation(
          parent: _controller,
          curve: new Interval(0.5, 1.0, curve: Curves.easeOut),
        );
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        ThemeData theme = Theme.of(context);
    
        return new Scaffold(
          appBar: new AppBar(),
          floatingActionButton: new FloatingActionButton(
            child: new Icon(Icons.flip_to_back),
            onPressed: () {
              setState(() {
                if (_controller.isCompleted || _controller.velocity > 0)
                  _controller.reverse();
                else
                  _controller.forward();
              });
            },
          ),
          body: new Center(
            child: new Stack(
              children: <Widget>[
                new AnimatedBuilder(
                  child: new MyCustomCard(colors: Colors.orange),
                  animation: _backScale,
                  builder: (BuildContext context, Widget child) {
                    final Matrix4 transform = new Matrix4.identity()
                      ..scale(1.0, _backScale.value, 1.0);
                    return new Transform(
                      transform: transform,
                      alignment: FractionalOffset.center,
                      child: child,
                    );
                  },
                ),
                new AnimatedBuilder(
                  child: new MyCustomCard(colors: Colors.blue),
                  animation: _frontScale,
                  builder: (BuildContext context, Widget child) {
                    final Matrix4 transform = new Matrix4.identity()
                      ..scale(1.0, _frontScale.value, 1.0);
                    return new Transform(
                      transform: transform,
                      alignment: FractionalOffset.center,
                      child: child,
                    );
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    0 讨论(0)
提交回复
热议问题