1

我正在尝试创建一个带有进度指示器的按钮 ( CircularProgressIndicator)

所需流量:

  1. 用户点击它应该触发功能的按钮
  2. 用户按下按钮(并按住),它应该触发动画并触发一个函数
  3. 当用户释放他们的持有时,它应该重置动画并触发一个函数

此时,我的代码在第二次按下(并按住)元素时起作用。第一次,动画控制器的 addListener 打印 2-3 次然后停止,而第二次,它保持正确并在用户持有元素时继续打印。无论如何,Ontap 功能都有效。

这是在 android 和 ios 设备上本地运行时发生的

剥离的代码块:

import 'package:flutter/material.dart';
import 'package:homi_frontend/constants/woopen_colors.dart';

class ProgressButton extends StatefulWidget {
  ProgressButton({
    @required this.onTap,
    @required this.onLongPress,
    @required this.onLongPressUp,
    this.duration = const Duration(seconds: 60),
  });

  final Function onTap;
  final Function onLongPress;
  final Function onLongPressUp;
  final Duration duration;

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

class ProgressButtonState extends State<ProgressButton>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  bool _beingPressed = false;

  @override
  void initState() {
    _animationController = AnimationController(
      vsync: this,
      duration: widget.duration,
    );

    _animationController.addListener(_animationListener);
    _animationController.addStatusListener(_animationStatusListener);

    super.initState();
  }

  void _animationListener() {
    print('Animation Controller Listener');
    setState(() {});
  }

  void _animationStatusListener(AnimationStatus status) {
    print('_animationStatusListener');
    if (status == AnimationStatus.completed) {
      print(
          'Completed duration of ${widget.duration}, fire _handleOnLongPressUp');
      _handleOnLongPressUp();
    }

    if (status == AnimationStatus.forward) {
      this.setState(() {
        _beingPressed = true;
      });
    }
  }

  void _handleOnLongPress() {
    print('_handleOnLongPress');
    try {
      _animationController.forward();
    } catch (e) {
      print('_handleOnLongPress error: ${e.toString()}');
    } finally {
      if (_animationController.status == AnimationStatus.forward) {
        print('Controller has been started, fire widget.onLongPress');
        widget.onLongPress();
      }
    }
  }

  void _handleOnLongPressUp() {
    print('_handleOnLongPressUp');
    try {
      this.setState(() {
        _beingPressed = false;
      });
      _animationController.reset();
    } catch (e) {
      print('_handleOnLongPressUp error: ${e.toString()}');
    } finally {
      if (_animationController.status == AnimationStatus.dismissed) {
        print('Controller has been dismissed, fire widget.onLongPressUp');
        widget.onLongPressUp();
      }
    }
  }

  @override
  dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      key: Key('progressButtonGestureDetector'),
      behavior: HitTestBehavior.opaque,
      onLongPress: _handleOnLongPress,
      onLongPressUp: _handleOnLongPressUp,
      onTap: widget.onTap,
      child: Container(
        width: 80,
        height: 80,
        child: Text(_animationController.value.toStringAsFixed(2)),
      ),
    );
  }
}

输出:

flutter: _handleOnLongPress
flutter: _animationStatusListener
flutter: Controller has been started, fire widget.onLongPress
(2) flutter: Animation Controller Listener

# here it just seems to loose its connection, but if I press (and hold) again, I get:

flutter: _handleOnLongPress
flutter: _animationStatusListener
flutter: Controller has been started, fire widget.onLongPress
(326) flutter: Animation Controller Listener
flutter: _handleOnLongPressUp
flutter: Animation Controller Listener
flutter: _animationStatusListener
flutter: Controller has been dismissed, fire widget.onLongPressUp

我也简要地研究过,但似乎RawGestureDetector只有我的手势会触发,那些不会……即使s 被删除。TapGestureRecognizerLongPressGestureRecognizerTapGestureRecognizer

_customGestures = Map<Type, GestureRecognizerFactory>();
_customGestures[TapGestureRecognizer] =
    GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
  () => TapGestureRecognizer(debugOwner: this),
  (TapGestureRecognizer instance) {
    instance
      ..onTapDown = (TapDownDetails details) {
        print('onTapDown');
      }
      ..onTapUp = (TapUpDetails details) {
        print('onTapUp');
      }
      ..onTap = () {
        print('onTap');
      }
      ..onTapCancel = () {
        print('onTapCancel');
      };
  },
);
_customGestures[LongPressGestureRecognizer] =
    GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
  () => LongPressGestureRecognizer(
      duration: widget.duration, debugOwner: this),
  (LongPressGestureRecognizer instance) {
    instance
      ..onLongPress = () {
        print('onLongPress');
      }
      ..onLongPressStart = (LongPressStartDetails details) {
        print('onLongPressStart');
        _animationController.forward();
      }
      ..onLongPressMoveUpdate = (LongPressMoveUpdateDetails details) {
        print('onLongPressMoveUpdate');
      }
      ..onLongPressEnd = (LongPressEndDetails details) {
        print('onLongPressEnd');
        _animationController.reset();
      }
      ..onLongPressUp = () {
        print('onLongPressUp');
      };
  },
);

请并感谢您的宝贵时间!

4

1 回答 1

1

您正在使用一个Text小部件来接收 中的点击 GestureDetector,与拇指相比,它有一个小的点击框。这可能是您偶尔会误点击点击框的原因。

您可以使用debugPaintPointersEnabled更清楚地查看行为(如果应用程序正在运行,则需要进行热重启):

import 'package:flutter/rendering.dart';

void main() {
  // Add the config here
  debugPaintPointersEnabled = true;
  runApp(App());
}

你可以看到命中框不会一直闪烁,即使我们认为我们点击了文本。为了提高准确性,让我们在 Text 周围包裹一个具有大小的 Container

GestureDetector(

      // ... other lines

      child: Container(
          width: 100,
          height: 50,
          color: Colors.blue,
          alignment: Alignment.center,
          child:
              Text('Value: ${_animationController.value.toStringAsFixed(2)}')),
    );

你可以看到hit box现在每次都在闪烁

于 2021-01-30T03:58:32.627 回答