-
[Flutter] Expandable bottom sheet dialog 를 직접 만들어보자IT/Flutter 2023. 6. 1. 23:33SMALL
오늘 만들어 볼 ui 는 Expandable bottom sheet dialog 이다.
위 그림처럼 드래그를 했을때 드래그 한 만큼 길이가 늘어나거나 줄어드는 인터렉션을 가진 ui 이다.
해당 ui를 만들기 위해서 필요한 것은 다음과 같다.
1. 드래그 이벤트가 발생할때마다 dy 차이(delta dy) 를 BottomSheetContainer 의 height 에 더해준다
2. 사이즈를 최소 미만 또는 최대 초과 할 수 없도록 한다.
3. 드래그 이벤트가 끝났을 때, 설정된 기준점에 도달했다면 사이즈를 최대로 늘리고 그렇지 않다면 최소로 줄인다.
첫번째로,
delta dy 를 BottomSheetContainer 의 기존 height 값에 더해주면, 드래그 하는만큼 컨테이너의 height 도 늘어남으로 마치 컨테이너의 크기가 마우스를 따라 늘었다 줄었다 하는것 같은 인터렉션을 만들 수 있다.
그럼, delta dy 는 어떻게 구할 수 있을까 ?
flutter 에서는 제스쳐를 감지할 수 있게 도와주는 widget 이 있는데 GestureDetector 위젯이 바로 그것이다.
GestureDetector 위젯의 onVerticalDragUpdate 콜백에서 해당 이벤트를 받을 수 있다.
/// A pointer that is in contact with the screen with a primary button and /// moving vertically has moved in the vertical direction. /// /// See also: /// /// * [kPrimaryButton], the button this callback responds to. final GestureDragUpdateCallback? onVerticalDragUpdate;
구현을 해보면...
Offset _updateOffset = Offset.zero; // update 시 delta offset double _bottomContainerHeight = 300; // 최소 컨테이너 높이 double get bottomContainerHeight => _bottomContainerHeight; set bottomContainerHeight (double value) { _bottomContainerHeight = value; } // GestureDetector( ..... /child : Container ... onVerticalDragUpdate: (value){ _updateOffset = value.delta; // delta offset final result = bottomContainerHeight - _updateOffset.dy; // 컨테이너 높이 최종 결과값 setState(() { bottomContainerHeight = result; // 결과를 높이에 반영하기 }); }, //.....)
위 아래로 드래그를 할 수 있게 되었다!
두번째로, 높이의 최소, 최대값을 설정할 차례이다.
여러 방법이 있겠지만 나는 간단히 컨테이너 높이의 최종 결과값이 최소값미만 또는 최대값 초과일 경우에 대해서는 높이를 반영하지 않는 방법을 선택했다.
final result = bottomContainerHeight - _updateOffset.dy; if(result < 300){ return; } if(result > MediaQuery.of(context).size.height - 100){ return; } setState(() { bottomContainerHeight = result; });
세번째로, 기준점에 따라 컨테이너의 크기를 조절해줄 단계이다.
GestureDetector가 제공해주는 콜백함수중에 OnVerticalDragEnd 가 있는데 이것을 활용하면 가능하다.
해당 콜백 안에서 드래그가 끝난 시점에 컨테이너의 크기를 기준점과 비교하여 그에따라 최소 또는 최대크기로 변경해주면 된다.
나는 최소는 300, 최대는 size.height - 100 으로 잡았고 기준점은 해당 값들의 중간지점으로 benchmark를 설정했다.
onVerticalDragEnd: (value){ final benchMark = (((MediaQuery.of(context).size.height - 100 ) - 300 )/ 2) + 300; print(benchMark); if(bottomContainerHeight < benchMark){ setState(() { bottomContainerHeight = 300; }); return; }else{ setState(() { bottomContainerHeight = MediaQuery.of(context).size.height - 100; }); return; } },
생각보다 어렵지않게 인터렉션을 만들어냈다!
일반적으로 드래그없이 크기를 조절하는것은 AnimatedContainer 같은 것을 활용하면 쉽게 만들 수 있지만 드래그를 사용하는것이 조금더 사용자 친화적으로 보인다. 또한 중간중간에 또다른 인터렉션을 만들수도 있으니 잘만 활용하면 참 좋을 것 같다.
소스코드 : https://github.com/sejun2/draggable_bottom_sheet/LIST'IT > Flutter' 카테고리의 다른 글
Flutter 에서 Element 와 RenderObject 를 재사용하는 방법 (0) 2024.02.24 [Flutter] Vertical scroll tabbar 을 만들어보자 (1) 2023.06.05 [Flutter] ios 빌드 시 Module "** *" not found 에러를 만날때 (2) 2023.05.15 [Flutter] RxDart 공식문서 보기 - 1 (6) 2023.01.03 [Flutter] TDD 실습해보기 - 1 (3) 2023.01.03