【问题标题】:Flutter hero animation between widgets not screens在小部件而不是屏幕之间颤动英雄动画
【发布时间】:2021-10-16 03:16:23
【问题描述】:

英雄动画最适合在屏幕之间导航,但我需要在小部件之间使用相同的动画。就像一张卡移动到另一个地方,例如:产品卡移动到购物车和其他东西。感谢您的回答!

【问题讨论】:

标签: flutter flutter-animation


【解决方案1】:

对于同一屏幕中的动画小部件,您可以使用 AnimatedPositioned 小部件,请参阅下面的代码

import 'dart:math';

import 'package:flutter/material.dart';

class AnimatedPositionedDemo extends StatefulWidget {
  const AnimatedPositionedDemo({Key? key}) : super(key: key);
  static String routeName = 'animated_positioned';

  @override
  _AnimatedPositionedDemoState createState() => _AnimatedPositionedDemoState();
}

class _AnimatedPositionedDemoState extends State<AnimatedPositionedDemo> {
  late double topPosition;
  late double leftPosition;

  double generateTopPosition(double top) => Random().nextDouble() * top;

  double generateLeftPosition(double left) => Random().nextDouble() * left;

  @override
  void initState() {
    super.initState();
    topPosition = generateTopPosition(30);
    leftPosition = generateLeftPosition(30);
  }

  void changePosition(double top, double left) {
    setState(() {
      topPosition = generateTopPosition(top);
      leftPosition = generateLeftPosition(left);
    });
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final appBar = AppBar(title: const Text('AnimatedPositioned'));
    final topPadding = MediaQuery.of(context).padding.top;
    // AnimatedPositioned animates changes to a widget's position within a Stack
    return Scaffold(
      appBar: appBar,
      body: SizedBox(
        height: size.height,
        width: size.width,
        child: Stack(
          children: [
            AnimatedPositioned(
              top: topPosition,
              left: leftPosition,
              duration: const Duration(seconds: 1),
              child: InkWell(
                onTap: () => changePosition(
                    size.height -
                        (appBar.preferredSize.height + topPadding + 50),
                    size.width - 150),
                child: Container(
                  alignment: Alignment.center,
                  width: 150,
                  height: 50,
                  child: Text(
                    'Click Me',
                    style: TextStyle(
                      color:
                          Theme.of(context).buttonTheme.colorScheme!.onPrimary,
                    ),
                  ),
                  color: Theme.of(context).primaryColor,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

希望对你有用

【讨论】:

    【解决方案2】:

    对于动画小部件,flutter 团队在 youtube 上提供了一个视频here

    你可以在他们的网站here阅读所有关于他们的信息

    【讨论】:

      【解决方案3】:

      这是添加到购物车的示例,add_cart_parabola:

      import 'dart:ui';
      import 'package:add_cart_parabola/add_cart_parabola.dart';
      import 'package:flutter/material.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
      
              primarySwatch: Colors.blue,
            ),
            home: MyHomePage(title: 'Flutter Demo Home Page'),
          );
        }
      }
      
      class MyHomePage extends StatefulWidget {
        MyHomePage({Key key, this.title}) : super(key: key);
      
        final String title;
      
        @override
        _MyHomePageState createState() => _MyHomePageState();
      }
      
      class _MyHomePageState extends State<MyHomePage> {
        int _counter = 0;
      
        GlobalKey floatKey = GlobalKey();
        GlobalKey rootKey = GlobalKey();
        Offset floatOffset ;
      
        @override
        void initState() {
          super.initState();
          WidgetsBinding.instance.addPostFrameCallback((_){
            RenderBox renderBox = floatKey.currentContext.findRenderObject();
            floatOffset = renderBox.localToGlobal(Offset.zero);
          });
        }
      
        @override
        Widget build(BuildContext context) {
      
          return Scaffold(
            appBar: AppBar(
      
              title: Text(widget.title),
            ),
            body: Container(
              key: rootKey,
              width: double.infinity,
              height: double.infinity,
              color: Colors.grey,
              child: ListView(
                children: List.generate(40, (index){
                  return generateItem(index);
                }).toList(),
              ),
            ),
            floatingActionButton: FloatingActionButton(
              backgroundColor: Colors.yellow,
              key: floatKey,
              tooltip: 'Increment',
              child: Icon(Icons.add),
            ),
          );
        }
        Widget generateItem(int index){
          Text text = Text("item $index",style: TextStyle(fontSize:
          25),);
      
          Offset temp;
          return GestureDetector(
            onPanDown: (details){
              temp = new Offset(details.globalPosition.dx, details.globalPosition
                  .dy);
            },
            onTap: (){
              Function callback ;
              setState(() {
                OverlayEntry entry = OverlayEntry(
                    builder: (ctx){
                      return ParabolaAnimateWidget(rootKey,temp,floatOffset,
                          Icon(Icons.cancel,color: Colors.greenAccent,),callback,);
                    }
                );
      
                callback = (status){
                  if(status == AnimationStatus.completed){
                    entry?.remove();
                  }
                };
      
                Overlay.of(rootKey.currentContext).insert(entry);
              });
            },
            child: Container(
              color: Colors.orange,
              child: text,
            ),
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-09-28
        • 2020-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-20
        • 1970-01-01
        • 2019-07-30
        • 2011-03-22
        相关资源
        最近更新 更多