2023. 6. 1. 23:33ㆍIT/Flutter
오늘 만들어 볼 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/
'IT > Flutter' 카테고리의 다른 글
Flutter 에서 Element 와 RenderObject 를 재사용하는 방법 (0) | 2024.02.24 |
---|---|
[Flutter] Vertical scroll tabbar 을 만들어보자 (0) | 2023.06.05 |
[Flutter] ios 빌드 시 Module "** *" not found 에러를 만날때 (0) | 2023.05.15 |
[Flutter] RxDart 공식문서 보기 - 1 (0) | 2023.01.03 |
[Flutter] TDD 실습해보기 - 1 (0) | 2023.01.03 |