gesture detector is blocked by somthing

30 Views Asked by At

in this widget the on tap gesture detector fails although the button is correctly positioned and on the most top layer , the functionality intended is the button to render only after the animation is completed and react to on tap events i made some tests to check if the animation might not end and be the culprit but that wasnt the case here is the widget that contains it , also notice that the button is directly positioned above a matching image

this is the widget that contains gesture detector

Widget buildImageWithTextAndLine(String imagePath, String text, int index) {
  bool isTapped = _tappedButtons[index] ?? false; // Safeguard against null

  return Column(
    children: [
      Stack(
        children: [
          Image.asset(imagePath, width: 319, height: 111.5),
          // Your positioning code remains unchanged
          if (_animationComplete)
            Positioned(
              top: buttonTopOffset,
              left: buttonLeftOffset,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _tappedButtons[index] = !isTapped; // Toggle the tapped state
                    print("Button $index tapped state: ${_tappedButtons[index]}");
                  });
                },
                child: Opacity(
                  opacity: buttonOpacity,
                  child: Container(
                    width: buttonWidth,
                    height: buttonHeight,
                    // Dynamically change color based on tap
                    color: isTapped ? Colors.red : const Color.fromARGB(255, 0, 0, 0),
                  ),
                ),
              ),
            ),
        ],
      ),
      SizedBox(height: widget.spaceBetweenImages),
    ],
  );
}

and this is the whole context file

import 'package:flutter/material.dart';

class Era extends StatefulWidget {
  final double topSpacing;
  final double spaceBetweenImages;
  final double spaceBetweenRows;

  const Era({
    Key? key,
    this.topSpacing = 35.0,
    this.spaceBetweenImages = 8,
    this.spaceBetweenRows = 60.0,
  }) : super(key: key);

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

class _EraState extends State<Era> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Offset> _leftColumnAnimation;
  late Animation<Offset> _rightColumnAnimation;
  bool _animationComplete = false;
  Map<int, bool> _tappedButtons = {};

  // Configurable variables for line and text
  final double lineWidth = 280.0;
  final double lineHeight = 0.5;
  final double lineTopOffset = 30.0;
  final double lineLeftOffset = 10.0;

  final double fontSize = 35.0;
  final double textTopOffset = 25.0;
  final double textLeftOffset = 10.0;

  // Button customization variables
  final double buttonWidth = 319.0; // You can adjust this
  final double buttonHeight = 111.5; // You can adjust this
  final double buttonTopOffset = 0.0; // You can adjust this
  final double buttonLeftOffset = 0.0; // You can adjust this
  final double buttonOpacity = 1; // Opacity of the button

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

    _controller.addListener(() {
      if (_controller.isCompleted) {
        setState(() {
          _animationComplete = true;
        });
      }
    });

    _leftColumnAnimation = Tween<Offset>(
      begin: const Offset(-1.5, 0.0),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeOut,
    ));

    _rightColumnAnimation = Tween<Offset>(
      begin: const Offset(1.5, 0.0),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeOut,
    ));

    _controller.forward();

    // Assuming the number of images/buttons is known and fixed
    int numberOfButtons = 6; // Adjust this based on your actual number of images/buttons
    for (int i = 0; i < numberOfButtons; i++) {
      _tappedButtons[i] = false;
    }
  }

  Widget buildImageWithTextAndLine(String imagePath, String text, int index) {
  bool isTapped = _tappedButtons[index] ?? false; // Safeguard against null

  return Column(
    children: [
      Stack(
        children: [
          Image.asset(imagePath, width: 319, height: 111.5),
          // Your positioning code remains unchanged
          if (_animationComplete)
            Positioned(
              top: buttonTopOffset,
              left: buttonLeftOffset,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _tappedButtons[index] = !isTapped; // Toggle the tapped state
                    print("Button $index tapped state: ${_tappedButtons[index]}");
                  });
                },
                child: Opacity(
                  opacity: buttonOpacity,
                  child: Container(
                    width: buttonWidth,
                    height: buttonHeight,
                    // Dynamically change color based on tap
                    color: isTapped ? Colors.red : const Color.fromARGB(255, 0, 0, 0),
                  ),
                ),
              ),
            ),
        ],
      ),
      SizedBox(height: widget.spaceBetweenImages),
    ],
  );
}


  @override
  Widget build(BuildContext context) {
    return Positioned(
      left: 0,
      right: 0,
      top: widget.topSpacing,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          SlideTransition(
            position: _leftColumnAnimation,
            child: Column(
              children: [
                buildImageWithTextAndLine('assets/conquest/swedishphase.png', "The Swedish Phase 1630", 0),
                buildImageWithTextAndLine('assets/conquest/frenchphase.png', "The French Phase 1635", 1),
                buildImageWithTextAndLine('assets/conquest/dutchship.png', "Cuba 1628", 2),
              ],
            ),
          ),
          SizedBox(width: widget.spaceBetweenRows),
          SlideTransition(
            position: _rightColumnAnimation,
            child: Column(
              children: [
                buildImageWithTextAndLine('assets/conquest/bohemianphase.png', "The Bohemian Phase 1618", 3),
                buildImageWithTextAndLine('assets/conquest/danishphase.png', "The Danish Phase 1625", 4),
                buildImageWithTextAndLine('assets/conquest/brazil.png', "Brazil 1624", 5),
              ],
            ),
          ),
        ],
      ),
    );
  }

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


i expect an answer to why gesture detector is blocked thats not because of the animation set to true i tested that and not because the gesture doesnt work in general it simply doesnt work in this file with that particular stack where the button is positioned over the img thats what might create this problem

0

There are 0 best solutions below