Эффект трепетания пользовательского масштаба onTap

#flutter #flutter-animation

#flutter #анимация flutter

Вопрос:

Я хотел бы создать пользовательский onTap (или любой из других onTap обратных вызовов, предоставляемых GestureDetector «индикатором», где содержимое (дочерний элемент) уменьшено, а текст становится темнее, например, так:пример

Существует ли уже готовый пакет для такого типа анимации? Если нет, можете ли вы, по крайней мере, исправить фрагмент ниже.

Я попытался создать его, используя AnimationController , Transform.scale и различные комбинации onTap обратных вызовов, но он практически не реагирует (все время «зависает»)

Вот основной фрагмент:

  double squareScaleA = 1;
  AnimationController _controllerA;
  @override
  void initState() {
    _controllerA = AnimationController(
        vsync: this,
        lowerBound: 0.9,
        upperBound: 1.0,
        duration: Duration(milliseconds: 100));
    _controllerA.addListener(() {
      setState(() {
        squareScaleA = _controllerA.value;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (dp) {
        _controllerA.forward();
      },
      onTapUp: (dp) {
        _controllerA.reverse();
      },
      child: Transform.scale(
        scale: squareScaleA,
        child: widget.child,
      ),
    );
  }
  

Ответ №1:

Я обнаружил проблему с моим кодом, анимация была «перевернута», при onTapDown это привело бы к child расширению (ничего не произошло, поскольку child масштаб уже был максимальным), поэтому я просто перевернул _controllerA.reverse и _controllerA.forward (фактически заменил _controllerA.forward на _controllerA.fling ). Это окончательный код:

 class OnTapScaleAndFade extends StatefulWidget {
  final Widget child;
  final void Function() onTap;
  const OnTapScaleAndFade({Key key, this.child, this.onTap}) : super(key: key);

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

class _OnTapScaleAndFadeState extends State<OnTapScaleAndFade>
    with TickerProviderStateMixin {
  double squareScaleA = 1;
  AnimationController _controllerA;
  @override
  void initState() {
    _controllerA = AnimationController(
      vsync: this,
      lowerBound: 0.98,
      upperBound: 1.0,
      value: 1,
      duration: Duration(milliseconds: 10),
    );
    _controllerA.addListener(() {
      setState(() {
        squareScaleA = _controllerA.value;
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTap: () {
        _controllerA.reverse();
        widget.onTap();
      },
      onTapDown: (dp) {
        _controllerA.reverse();
      },
      onTapUp: (dp) {
        Timer(Duration(milliseconds: 150), () {
          _controllerA.fling();
        });
      },
      onTapCancel: () {
        _controllerA.fling();
      },
      child: Transform.scale(
        scale: squareScaleA,
        child: widget.child,
      ),
    );
  }

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

Не стесняйтесь добавлять свои пользовательские обратные вызовы жестов, мне нужен был только onTap.

Ответ №2:

Использование zoom_tap_animation: ^1.1.0

Он обрабатывает то, что вам нужно.

Использование:

виджет ZoomTapAnimation используется по умолчанию

 ZoomTapAnimation(
      onTap: (){},
      child: YOUR_WIDGET
);
  

и вы также можете определить пользовательские параметры

 ZoomTapAnimation(
      child: YOUR_WIDGET,
      onTap: (){},
      onLongTap: (){},
      enableLongTapRepeatEvent: false,
      longTapRepeatDuration: const Duration(milliseconds: 100),
      begin: 1.0,
      end: 0.93,
      beginDuration: const Duration(milliseconds: 20),
      endDuration: const Duration(milliseconds: 120),
      beginCurve: Curves.decelerate,
      endCurve: Curves.fastOutSlowIn
);
  

дополнительная информация здесь: https://pub.dev/packages/zoom_tap_animation

Ответ №3:

Вы можете попробовать этот пакет для паба. Вы можете изменить анимацию по своему усмотрению. С помощью scaleCoefficient вы можете регулировать скорость. Если вы обернете им виджет So, он будет выглядеть анимированным

https://pub.dev/packages/spring_button Пример;

 SpringButton(
          SpringButtonType.OnlyScale,
          row(
            "Increment",
            Colors.deepPurpleAccent,
          ),
          onTapDown: (_) => incrementCounter(),
          onLongPress: () => timer = Timer.periodic(
            const Duration(milliseconds: 100),
            (_) => incrementCounter(),
          ),
          onLongPressEnd: (_) {
            timer?.cancel();
          },
        ),
      ),
  

Комментарии:

1. Спасибо за ваш ответ, но данный пакет, похоже, не работает, мой дочерний виджет не будет анимироваться