157 lines
5.4 KiB
Dart
157 lines
5.4 KiB
Dart
import 'dart:math';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'swipe/swipe_controller.dart';
|
|
import 'swipe/swipe_config.dart';
|
|
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
|
|
|
|
class HIEdgeSwipeDetector extends StatefulWidget {
|
|
final Widget child;
|
|
final double reservedEdgeWidth;
|
|
final double detectionEdgeWidth;
|
|
final double minSwipeDistance;
|
|
final double minSwipeVelocity;
|
|
final SwipeConfig? config;
|
|
const HIEdgeSwipeDetector(
|
|
{super.key,
|
|
required this.child,
|
|
this.reservedEdgeWidth = 0,
|
|
this.detectionEdgeWidth = 20,
|
|
this.minSwipeDistance = 20,
|
|
this.minSwipeVelocity = 300,
|
|
this.config});
|
|
@override
|
|
State<HIEdgeSwipeDetector> createState() => _HIEdgeSwipeDetectorState();
|
|
}
|
|
|
|
class _HIEdgeSwipeDetectorState extends State<HIEdgeSwipeDetector> {
|
|
Offset? _start;
|
|
Offset? _last;
|
|
DateTime? _startTime;
|
|
final SwipeController _controller =
|
|
Get.put(SwipeController(), permanent: true);
|
|
bool _fromLeft = false;
|
|
bool _fromRight = false;
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
KRLogUtil.kr_d('HIEdgeSwipeDetector build');
|
|
return Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
widget.child,
|
|
Positioned(
|
|
left: 0,
|
|
top: 0,
|
|
bottom: 0,
|
|
width: widget.detectionEdgeWidth,
|
|
child: GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onHorizontalDragStart: (details) {
|
|
_fromLeft = true;
|
|
_fromRight = false;
|
|
_start = details.globalPosition;
|
|
_startTime = DateTime.now();
|
|
KRLogUtil.kr_d('dragStart LEFT x=${details.globalPosition.dx}',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
},
|
|
onHorizontalDragUpdate: (details) {
|
|
_last = details.globalPosition;
|
|
KRLogUtil.kr_d('dragUpdate LEFT dx=${details.delta.dx}',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
},
|
|
onHorizontalDragEnd: (details) {
|
|
if (_start == null || _startTime == null) return;
|
|
final durationMs =
|
|
DateTime.now().difference(_startTime!).inMilliseconds;
|
|
final velocity = details.velocity.pixelsPerSecond.dx.abs();
|
|
final distance = _last != null ? (_last!.dx - _start!.dx) : 0.0;
|
|
final okByVelocity = velocity >= widget.minSwipeVelocity;
|
|
final okByDistance = distance.abs() >= widget.minSwipeDistance;
|
|
KRLogUtil.kr_d(
|
|
'dragEnd LEFT vel=${details.velocity.pixelsPerSecond.dx} dur=$durationMs dist=$distance okV=$okByVelocity okD=$okByDistance',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
if (!okByVelocity && !okByDistance) {
|
|
_reset();
|
|
return;
|
|
}
|
|
if (distance > 0) {
|
|
final cfg = widget.config;
|
|
if (cfg == null || !cfg.enableLeft) {
|
|
_reset();
|
|
return;
|
|
}
|
|
if (cfg.onLeft != null) {
|
|
cfg.onLeft!();
|
|
} else {
|
|
Get.back();
|
|
}
|
|
}
|
|
_reset();
|
|
},
|
|
),
|
|
),
|
|
Positioned(
|
|
right: 0,
|
|
top: 0,
|
|
bottom: 0,
|
|
width: widget.detectionEdgeWidth,
|
|
child: GestureDetector(
|
|
behavior: HitTestBehavior.opaque,
|
|
onHorizontalDragStart: (details) {
|
|
_fromLeft = false;
|
|
_fromRight = true;
|
|
_start = details.globalPosition;
|
|
_startTime = DateTime.now();
|
|
KRLogUtil.kr_d('dragStart RIGHT x=${details.globalPosition.dx}',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
},
|
|
onHorizontalDragUpdate: (details) {
|
|
_last = details.globalPosition;
|
|
KRLogUtil.kr_d('dragUpdate RIGHT dx=${details.delta.dx}',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
},
|
|
onHorizontalDragEnd: (details) {
|
|
if (_start == null || _startTime == null) return;
|
|
final durationMs =
|
|
DateTime.now().difference(_startTime!).inMilliseconds;
|
|
final velocity = details.velocity.pixelsPerSecond.dx.abs();
|
|
final distance = _last != null ? (_last!.dx - _start!.dx) : 0.0;
|
|
final okByVelocity = velocity >= widget.minSwipeVelocity;
|
|
final okByDistance = distance.abs() >= widget.minSwipeDistance;
|
|
KRLogUtil.kr_d(
|
|
'dragEnd RIGHT vel=${details.velocity.pixelsPerSecond.dx} dur=$durationMs dist=$distance okV=$okByVelocity okD=$okByDistance',
|
|
tag: 'HIEdgeSwipeDetector');
|
|
if (!okByVelocity && !okByDistance) {
|
|
_reset();
|
|
return;
|
|
}
|
|
if (distance < 0) {
|
|
final cfg = widget.config;
|
|
if (cfg == null || !cfg.enableRight) {
|
|
_reset();
|
|
return;
|
|
}
|
|
if (cfg.onRight != null) {
|
|
cfg.onRight!();
|
|
} else {
|
|
_controller.openRightMenu();
|
|
}
|
|
}
|
|
_reset();
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
void _reset() {
|
|
_start = null;
|
|
_last = null;
|
|
_startTime = null;
|
|
_fromLeft = false;
|
|
_fromRight = false;
|
|
}
|
|
}
|