简体   繁体   English

Flutter:在 Stack 中的动画图像上触发 GestureDetector

[英]Flutter: Triggering GestureDetector on animated images in Stack

I have an animated "flower" made up of petal images that rotate into position on Widget build.我有一个由花瓣图像组成的动画“花”,这些图像在 Widget 构建中旋转到位。 The petal images can be of various lengths.花瓣图像可以是各种长度。

Because I didn't know how to move the pivot point of each petal PNG to the bottom centre for the rotation, I made each petal image a transparent square with the bottom of the petal in the centre of the image, so I can just rotate the entire square image around the centre and it looks like the petal is rotating around its base.因为我不知道如何将每个花瓣 PNG 的枢轴点移动到底部中心进行旋转,所以我将每个花瓣图像制作成一个透明的正方形,花瓣的底部位于图像的中心,所以我可以旋转围绕中心的整个方形图像,看起来花瓣围绕着它的底部旋转。

I have 5 of these in a stack, animated, and I want a gesture detector on each one so I can take action when any of them are tapped.我在堆栈中有 5 个动画,我希望每个都有一个手势检测器,这样我就可以在点击其中任何一个时采取行动。 I already have a GestureDetector on an image I use for the centre of the flower and it works, but none of the petals do.我已经在用于花中心的图像上安装了 GestureDetector 并且它可以工作,但没有一个花瓣可以。

I have tried using HitTestBehavior.translucent with no luck...我试过使用 HitTestBehavior.translucent 没有运气......

class _PFMainScreenState extends State<PFMainScreen>
    with TickerProviderStateMixin {
  AnimationController rotationController;

  @override
  void initState() {
    super.initState();
    rotationController = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
  }

  void onAfterBuild(BuildContext context) {
    Future.delayed(const Duration(milliseconds: 1000), () {
      rotationController.forward();
    });
  }

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

  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => onAfterBuild(context));
    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: DecoratedBox(
          position: DecorationPosition.background,
          decoration: BoxDecoration(
            color: Colors.black,
            image: DecorationImage(
                image: AssetImage('images/background.jpg'),
                fit: BoxFit.contain),
          ),
          child: Stack(
            children: <Widget>[
              Center(
                child: GestureDetector(
                    onTap: () {
                      print('1st image tapped');
                    },
                    behavior: HitTestBehavior.translucent,
                    child: Image.asset('images/petal-square.png', height: 350)),
              ),
              Center(
                child: RotationTransition(
                  turns: Tween(begin: 0.0, end: 0.2).animate(
                      new CurvedAnimation(
                          parent: rotationController,
                          curve: Curves.decelerate,
                          reverseCurve: Curves.decelerate)),
                  child: GestureDetector(
                      onTap: () {
                        print('2nd image tapped');
                      },
                      behavior: HitTestBehavior.translucent,
                      child:
                          Image.asset('images/petal-square.png', height: 250)),
                ),
              ),
              Center(
                child: RotationTransition(
                  turns: Tween(begin: 0.0, end: 0.4).animate(
                      new CurvedAnimation(
                          parent: rotationController,
                          curve: Curves.decelerate,
                          reverseCurve: Curves.decelerate)),
                  child: Image.asset('images/petal-square.png', height: 400),
                ),
              ),
              Center(
                child: RotationTransition(
                  turns: Tween(begin: 0.0, end: 0.6).animate(
                      new CurvedAnimation(
                          parent: rotationController,
                          curve: Curves.decelerate,
                          reverseCurve: Curves.decelerate)),
                  child: Image(
                    image: AssetImage('images/petal-square.png'),
                  ),
                ),
              ),
              Center(
                child: RotationTransition(
                  turns: Tween(begin: 0.0, end: 0.8).animate(
                      new CurvedAnimation(
                          parent: rotationController,
                          curve: Curves.decelerate,
                          reverseCurve: Curves.decelerate)),
                  child: Image.asset('images/petal-square.png', height: 200),
                ),
              ),
              Center(
                child: GestureDetector(
                  onTap: () {
                    //rotationController.forward(from: 0.0);
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => PFMenuScreen(),
                      ),
                    );
                  },
                  behavior: HitTestBehavior.translucent,
                  child: Image(
                    height: 100.0,
                    width: 100.0,
                    image: AssetImage('images/centre.png'),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Is there a way to detect taps on non-translucent images in a Stack?有没有办法检测堆栈中非半透明图像的点击?

Cheers干杯

If you run your app with the flutter inspector of Dart Dev Tools, you can see that each of your Center widgets are filling the whole screen.如果您使用 Dart Dev Tools 的 flutter 检查器运行您的应用程序,您可以看到您的每个Center小部件都填满了整个屏幕。 That may effect your gesture detection depending on where you put your gesture detector.这可能会影响您的手势检测,具体取决于您放置手势检测器的位置。

Dart 开发工具中的 Flutter 检查器图像

Here is some code that should work for you.这是一些应该适合您的代码。 I refactored your rotating image into a re-usable widget.我将您的旋转图像重构为可重复使用的小部件。

class PFMainScreen extends StatefulWidget {
  @override
  _PFMainScreenState createState() => _PFMainScreenState();
}

class _PFMainScreenState extends State<PFMainScreen>
    with TickerProviderStateMixin {
  AnimationController rotationController;

  @override
  void initState() {
    super.initState();
    rotationController = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
  }

  void onAfterBuild(BuildContext context) {
    Future.delayed(const Duration(milliseconds: 1000), () {
      rotationController.forward();
    });
  }

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

  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => onAfterBuild(context));
    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: Stack(
          alignment: AlignmentDirectional.center,
          children: <Widget>[
            RotatingImage(
              rotationController: rotationController,
              onTap: () {
                print("Image 1 tapped");
              },
              imageHeight: 400,
              tweenEnd: 0.2,
            ),
            RotatingImage(
              rotationController: rotationController,
              onTap: () {
                print("Image 2 tapped");
              },
              imageHeight: 350,
              tweenEnd: 0.4,
            ),
            RotatingImage(
              rotationController: rotationController,
              onTap: () {
                print("Image 3 tapped");
              },
              imageHeight: 250,
              tweenEnd: 0.6,
            ),
            RotatingImage(
              rotationController: rotationController,
              onTap: () {
                print("Image 4 tapped");
              },
              imageHeight: 200,
              tweenEnd: 0.8,
            ),
          ],
        ),
      ),
    );
  }
}

class RotatingImage extends StatelessWidget {
  final AnimationController rotationController;
  final double imageHeight;
  final double tweenEnd;
  final Function onTap;
  const RotatingImage({
    this.onTap,
    this.imageHeight,
    this.tweenEnd,
    @required this.rotationController,
  });

  @override
  Widget build(BuildContext context) {
    return RotationTransition(
      turns: Tween(begin: 0.0, end: tweenEnd).animate(new CurvedAnimation(
          parent: rotationController,
          curve: Curves.decelerate,
          reverseCurve: Curves.decelerate)),
      child: GestureDetector(
          onTap: onTap,
          behavior: HitTestBehavior.translucent,
          child: Image.asset('images/petal-square.png', height: imageHeight)),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM