admin管理员组

文章数量:1123709

I want a very simple animation that is turning to be not that simple.

This is how it behaves now. I need it to have smooth transitions between states and the buttons to take full available width of the screen when they are clicked.

I have tried using width: double.infinity or Expanded() with AnimatedContainer, but none of them work. I also tried with AnimatedBuilder() but the behavior was very messy. This is my code:

class AttendanceButtons extends StatefulWidget {
  const AttendanceButtons({super.key});

  @override
  State<AttendanceButtons> createState() => _AttendanceButtonsState();
}

class _AttendanceButtonsState extends State<AttendanceButtons> {
  @override
  Widget build(BuildContext context) {
    final controller = Provider.of<EventDetailsController>(context);

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: Spacings.m),
      child: Row(
        children: [
          AnimatedContainer(
            duration: Duration(milliseconds: 500),
            child: controller.userAttendanceStatus == AttendanceStatus.none
                ? Expanded(
                  child: const Text(
                      'Are you up for it?',
                      maxLines: 1,
                    ),
                )
                : const SizedBox.shrink(),
          ),
          AttendanceButton(
            text: "Considering",
            icon: Icons.question_mark,
            isExpanded: controller.isConsidering,
            onPressed: () =>
                controller.setAttendance(status: AttendanceStatus.considering),
          ),
          const SizedBox(width: Spacings.s),
          AttendanceButton(
            text: "Up for it",
            icon: Icons.check,
            isExpanded: controller.isAttending,
            onPressed: () =>
                controller.setAttendance(status: AttendanceStatus.attending),
          ),
        ],
      ),
    );
  }
}

class AttendanceButton extends StatefulWidget {
  final String text;
  final IconData icon;
  final bool isExpanded;
  final Function onPressed;

  const AttendanceButton({
    super.key,
    required this.text,
    required this.icon,
    this.isExpanded = false,
    required this.onPressed,
  });

  @override
  State<AttendanceButton> createState() => _AttendanceButtonState();
}

class _AttendanceButtonState extends State<AttendanceButton> {
  Widget child() {
    return ElevatedButton.icon(
      onPressed: () => widget.onPressed(),
      icon: Icon(widget.icon),
      label: widget.isExpanded
          ? Text(
              widget.text,
              maxLines: 1,
            )
          : const SizedBox(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      height: 40,
      duration: Duration(milliseconds: 100),
      child: widget.isExpanded ? Expanded(child: child()) : child(),
    );
  }
}

Expected behavior:

In case it is not understood, the expected behavior is the following:

  • When user clicks on "considering" button, it expands to take full available width of the screen. The text "Are you up for it?" shrinks to the left until it disappears and the other button shrinks to the right if it was expanded before, leaving the small state that only displays the check icon. The result will be the "Considering" button with the question mark icon occupying all the width except for the paddings and the button with the check mark. The content of the button is displayed on the center.
  • When the user clicks on "up for it" button, the behavior is the same as before. Only one button can be clicked at a time. The animations of both buttons (one expanding and one shrinking) happen at the same time.
  • When the user unclicks both buttons, the text appears by growing on width, aligned to the left, until it ends up taking full available width. The clicked button shrinks at the same time, aligned to the right, until it only takes the necessary width to display the icon.

本文标签: How to do a Flutter animation to full available widthStack Overflow