N coding
Flutter : Flutter onDrawerSlide 구현하기 본문
https://www.notion.so/Drawer-onPositionChanged-1292141c52334e0abca936fed3f7a603
Android로 치자면 DrawerListener.[onDrawerSlide](https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout.DrawerListener#onDrawerSlide(android.view.View, float)) 같은 것
Flutter는 2.0 에서 업데이트 된 Scaffold.onDrawerChanged로 open인지 close 인지만 알 수 있다.
open/close 여부는 내부 코드를 까보면 drawer의 위치가 0.5를 기준으로 변한다.
그렇다면 onDrawerSlide 처럼 몇 퍼센트 정도 열렸는지를 알 수는 없을까? ⇒ 정식으로는 없다.
하지만 돌고돌아서 구현해낼 수는 있다.
1. 코드 수정하기
당연히 권장되는 방법은 아니지만 Drawer 위젯 내부 코드를 수정하면 가져올 수 있다.
AnimationController의 value를 가져오거나 읽어오면 된다.
class DrawerControllerState extends State<DrawerController> with SingleTickerProviderStateMixin {
@override
void initState() {
super.initState();
_scrimColorTween = _buildScrimColorTween();
_controller = AnimationController(
value: widget.isDrawerOpen ? 1.0 : 0.0,
duration: _kBaseSettleDuration,
vsync: this,
);
_controller
..addListener(_animationChanged)
..addStatusListener(_animationStatusChanged);
}
...
}
2. 직접 Drawer를 구현하기 or 구현된 Plugin을 찾기
엄청나게 잘 만들어진 라이브러리, 플러그인들이 많다. 특정한 걸 하고 싶은 게 아니라 그냥 화려한 효과를 원한다면 좋은 선택일 것 같다.
https://www.youtube.com/watch?v=ZHRhSFXqHJY
Flutter Animated Navigation Drawer
3. Drawer의 현재 position을 알아내서 내가 움직이고 싶은 것을 움직이기
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
class DrawerListener extends StatefulWidget {
final Widget child;
final void Function(FractionalOffset offset) onPositionChange;
DrawerListener({
required this.child,
this.onPositionChange,
});
@override
_DrawerListenerState createState() => _DrawerListenerState();
}
class _DrawerListenerState extends State<DrawerListener> {
int taskID;
Offset currentOffset;
@override
void initState() {
super.initState();
_postTask();
}
_postTask() {
taskID = SchedulerBinding.instance.scheduleFrameCallback((_) {
if (widget.onPositionChange != null) {
final box = context?.findRenderObject();
if (box != null) {
Offset newOffset = box.globalToLocal(Offset.zero);
if (newOffset != currentOffset) {
currentOffset = newOffset;
widget.onPositionChange(
FractionalOffset.fromOffsetAndRect(
currentOffset,
Rect.fromLTRB(0, 0, box.size.width, box.size.height),
),
);
}
}
}
_postTask();
});
}
@override
void dispose() {
SchedulerBinding.instance.cancelFrameCallbackWithId(taskID);
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.child,
}
}
Flutter: possible to detect when a drawer is open?
이 stackoverflow에 달린 답변이 그나마 도움이 되었다. 나는 거의 flutter + drawer로 검색된 모든 글을 읽고 다녔는데 이게 내가 원하던 답에 가장 근접했음.
Drawer(child)의 RenderObject의 Local에서의 위치를 찾은 뒤,
그 Offset이 현재 box(child = Drawer) 크기에 비해 얼마의 비율인지를 FractionalOffset으로 계산해서 onPositionChange의 인자로 넘겨준다.
width의 위치 비율만을 보고 싶으면 currentOffset.dx / box.size.width 처럼 계산해도 될 것 같다.
이렇게 구현을 하면, 본인이 onPositionChange를 사용하는 것?에 따라서 자연스러울 수도 있고, 완전히 자연스럽게 보이지는 않을 수도 있다. 내 경우는 좀 버벅임이 있었다.
ScheduleBinding.instance.scheduleFrameCallback이 build 이후에 schedule해놓는 거라서 빌드 속도나 Drawer를 드래그하는 속도에 따라서 수치가 휙휙 바뀌는 경우에는 좀 부자연스러웠음. 그래도 없는 것보다는 나으니 그냥 썼다 대충.
더 좋은 방법이 있으면 comment를 남겨주세요..!
아니면 비슷하게 GestureDetector로 현재 Drag되는 위치, 손가락이 움직인 정도를 가지고 파악을 해도 될 것 같다.
https://stackoverflow.com/questions/47272323/flutter-get-the-local-position-from-the-gesturedetector
issue도 있고,.. Priority는 비록 높진 않지만 언젠가는 되겠지.. 안 어렵잖아 ㅠ 해줘
'Dart&Flutter' 카테고리의 다른 글
Flutter : How to develop flutter on tizen? (0) | 2022.01.20 |
---|---|
Dart : async/await/Future (0) | 2022.01.20 |
Flutter : FFI (0) | 2022.01.20 |
Dart : what is extenstion ? extension keyword (0) | 2022.01.20 |
Dart : enum with values (enum-like class) (0) | 2022.01.20 |