Home > Back-end >  Stack is blocking for widget buttons expanding
Stack is blocking for widget buttons expanding

Time:04-13

From enter image description here

import 'package:flutter/material.dart';
import 'dart:math';
import 'package:vector_math/vector_math.dart' show radians, Vector3;
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter',
        home: Scaffold(
            body: SizedBox.expand(child: Stack(children: [Positioned(
                top: 400,
                left: 150,
                child: RadialMenu())]))));
  }
}

class RadialMenu extends StatefulWidget {
  createState() => _RadialMenuState();
}

class _RadialMenuState extends State<RadialMenu> with SingleTickerProviderStateMixin {

  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(duration: Duration(milliseconds: 900), vsync: this);
    // ..addListener(() => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    return RadialAnimation(key: UniqueKey(), controller: controller);
  }

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


class RadialAnimation extends StatelessWidget {
  RadialAnimation({ required Key key, required this.controller }) :

        translation = Tween<double>(
          begin: 0.0,
          end: 100.0,
        ).animate(
          CurvedAnimation(
              parent: controller,
              curve: Curves.elasticOut
          ),
        ),

        scale = Tween<double>(
          begin: 1.5,
          end: 0.0,
        ).animate(
          CurvedAnimation(
              parent: controller,
              curve: Curves.fastOutSlowIn
          ),
        ),

        rotation = Tween<double>(
          begin: 0.0,
          end: 360.0,
        ).animate(
          CurvedAnimation(
            parent: controller,
            curve: Interval(
              0.0, 0.7,
              curve: Curves.decelerate,
            ),
          ),
        ),

        super(key: key);

  final AnimationController controller;
  final Animation<double> rotation;
  final Animation<double> translation;
  final Animation<double> scale;

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (context, widget) {
          return Transform.rotate(
              angle: radians(rotation.value),
              child: Stack(
                  alignment: Alignment.center,
                  children: <Widget>[
                    _buildButton(0, color: Colors.red, icon: FontAwesomeIcons.thumbtack),
                    _buildButton(45, color: Colors.green, icon:FontAwesomeIcons.sprayCan),
                    _buildButton(90, color: Colors.orange, icon: FontAwesomeIcons.fire),
                    _buildButton(135, color: Colors.blue, icon:FontAwesomeIcons.kiwiBird),
                    _buildButton(180, color: Colors.black, icon:FontAwesomeIcons.cat),
                    _buildButton(225, color: Colors.indigo, icon:FontAwesomeIcons.paw),
                    _buildButton(270, color: Colors.pink, icon: FontAwesomeIcons.bong),
                    _buildButton(315, color: Colors.yellow, icon:FontAwesomeIcons.bolt),
                    Transform.scale(
                      scale: scale.value - 1,
                      child: FloatingActionButton(child: Icon(FontAwesomeIcons.timesCircle), onPressed: _close, backgroundColor: Colors.red),
                    ),
                    Transform.scale(
                      scale: scale.value,
                      child: FloatingActionButton(child: Icon(FontAwesomeIcons.solidDotCircle), onPressed: _open),
                    )

                  ])
          );
        });
  }

  _open() {
    controller.forward();
  }

  _close() {
    controller.reverse();
  }

  _buildButton(double angle, { required Color color, required IconData icon }) {
    final double rad = radians(angle);
    return Transform(
        transform: Matrix4.identity()..translate(
            (translation.value) * cos(rad),
            (translation.value) * sin(rad)
        ),

        child: FloatingActionButton(
            child: Icon(icon), backgroundColor: color, onPressed: _close, elevation: 0)
    );
  }
}

CodePudding user response:

The Stack isn't blocking the buttons. Actually, it is not even aware of its children. When you apply the Matrix transformation to the buttons, you push them outside the Stack widget, which prevents them from receiving pointer events.

May not be an ideal workaround depending on your case, but providing the Stack a height and width will fix the issue. The buttons will remain within the boundaries of the Stack even after the transformation:

Stack(
  alignment: Alignment.center,
  children: <Widget>[
    const SizedBox(height: 250, width: 250), // <== Add this line to the top
    _buildButton(0, color: Colors.red, icon: Icons.clear),
    _buildButton(45, color: Colors.green, icon: Icons.clear),
    _buildButton(90, color: Colors.orange, icon: Icons.clear),
    _buildButton(135, color: Colors.blue, icon: Icons.clear),
    _buildButton(180, color: Colors.black, icon: Icons.clear),
    _buildButton(225, color: Colors.indigo, icon: Icons.clear),
    _buildButton(270, color: Colors.pink, icon: Icons.clear),
    _buildButton(315, color: Colors.yellow, icon: Icons.clear),
    Transform.scale(
      scale: scale.value - 1,
      child: FloatingActionButton(
          child: Icon(Icons.clear),
          onPressed: _close,
          backgroundColor: Colors.red),
    ),
    Transform.scale(
      scale: scale.value,
      child: FloatingActionButton(
          child: Icon(Icons.clear), onPressed: _open),
    )
  ],
)

  • Related