flutterdartuser-interfaceanimationuser-experience

I would like to set AnimatedOpacity to only a part, but it will only be reflected in the terminal child widget


I want to create a button that displays a border while being pressed. However, I want to control whether the border is shown or hidden using AnimatedOpacity, but the button itself becomes hidden. How can I make the button itself visible all the time, but only the border can be controlled by AnimatedOpacity?

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

class AppAnimatedButton extends HookWidget {
  const AppAnimatedButton({
    required double borderRadius,
    required Future<void> Function() onTap,
    bool? isSecondFlameBorder,
    super.key,
  })  : _borderRadius = borderRadius,
        _isSecondFlameBorder = isSecondFlameBorder ?? false,
        _onTap = onTap;

  final bool _isSecondFlameBorder;
  final double _borderRadius;
  final Future<void> Function() _onTap;

  @override
  Widget build(BuildContext context) {
    final isTapDowning = useState(false);
    const radius = 10.0;

    return GestureDetector(
      onTapCancel: () => isTapDowning.value = false,
      onTapDown: (_) => isTapDowning.value = true,
      onTapUp: (_) async {
        isTapDowning.value = false;
        _onTap();
      },
      child: AnimatedOpacity(
        opacity: isTapDowning.value ? 1 : 0,
        curve: Curves.easeIn,
        duration: const Duration(milliseconds: 400),
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(
              color: _isSecondFlameBorder && isTapDowning.value
                  ? Colors.blue
                  : Colors.transparent,
              width: 4,
            ),
            borderRadius: BorderRadius.circular(_borderRadius * 1.55),
          ),
          child: Container(
            width: 100,
            height: 100,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(radius),
              color: Colors.yellow,
            ),
          ),
        ),
      ),
    );
  }
}

For reference, I wanted to create an animation like this for the Amazon app. enter image description here


Solution

  • You can remove the AnimatedOpacity widget that is wrapping the first Container, and change that Container to AnimatedContainer. Use the same curve and duration that was on the AnimatedOpacity before to the AnimatedContainer.

    return GestureDetector(
      // ...
      child: AnimatedContainer(
        curve: Curves.easeIn,
        duration: const Duration(milliseconds: 400),
        decoration: BoxDecoration(
          // ...
        ),
        child: Container(
          width: 100,
          height: 100,
          // ...
        ),
      ),
    );