JJ_MKVMaker/lib/ui/app_bar/swipe_nav.dart

46 lines
1.8 KiB
Dart

/// 약속: 좌우로 밀어 다른 화면으로 옮기기 ([SwipeNav]) - 환경 설정 "밀어서 화면 이동" 을 따른다.
library;
import 'package:flutter/material.dart';
import 'app_nav_buttons.dart';
/// 화면 가운데를 좌우로 밀면 다음 · 이전 화면으로 (환경 설정 > 컴포넌트 의 순서, 끝 다음은 처음).
/// 안쪽의 옆으로 밀리는 것 (가로 목록 · 막대) 이 먼저 받고, 위 · 아래 가장자리 (1/5) 에서 시작한 것은 무시한다.
class SwipeNav extends StatefulWidget {
final String current;
final Widget child;
/// 높이 어디서 시작해도 (위쪽 막대처럼 작은 곳에 씌울 때)
final bool anywhere;
const SwipeNav({super.key, required this.current, required this.child, this.anywhere = false});
@override
State<SwipeNav> createState() => _SwipeNavState();
}
class _SwipeNavState extends State<SwipeNav> {
bool _middle = false;
@override
Widget build(BuildContext context) {
final scope = AppScope.maybeOf(context);
if (scope == null) return widget.child;
return GestureDetector(
behavior: HitTestBehavior.translucent,
onHorizontalDragStart: (d) {
final h = context.size?.height ?? 0;
_middle = widget.anywhere || (h > 0 && d.localPosition.dy > h * 0.2 && d.localPosition.dy < h * 0.8);
},
onHorizontalDragEnd: (d) {
final v = d.primaryVelocity ?? 0;
// 켜고 끄기는 밀 때 확인 (이 위젯은 설정이 바뀌어도 다시 그려지지 않을 수 있음)
if (!scope.controller.settings.display.swipeNav || !_middle || v.abs() < 500) return;
// 왼쪽으로 밀면 다음 화면, 오른쪽으로 밀면 이전 화면
AppNavButtons.step(context, widget.current, v < 0 ? 1 : -1);
},
child: widget.child,
);
}
}