46 lines
1.8 KiB
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,
|
|
);
|
|
}
|
|
}
|