최대 크기(화면 전체였다)로 키웠을 때 그림자가 사라지게 하는 기능이 필요해서 그 부분만 추가로 작업해주었다.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class flickFrameCommon extends StatefulWidget {
var mode; //soft, hard
bool enabled;
double height;
double minHeight;
double maxHeight;
double middleHeight;
EdgeInsets padding;
Function changeHeight;//높이 값이 변화할 때 마다 flickFrameCommon를 호출한 곳에서 높이를 돌려 받을 수 있음
Widget child;
flickFrameCommon({
Key key,
this.mode = "soft",
this.enabled = true,
this.height = 52.0,
this.minHeight,
this.maxHeight,
this.middleHeight,
this.padding,
this.changeHeight,
@required this.child,
}) : super(key: key);
@override
_flickFrameCommonState createState() => _flickFrameCommonState();
}
class _flickFrameCommonState extends State<flickFrameCommon> {
int shadowAlpha = 125;
double prevHeight;
double Sensitivity = 100; //감도
@override
void initState() {
super.initState();
prevHeight = widget.height;
if (widget.minHeight == null) {
if (30 < widget.height && widget.height < 118.7 ) {
widget.minHeight = widget.height;
} else {
widget.minHeight = 118.7;
}
}
if (widget.mode != "hard" && widget.mode != "soft") {
throw ArgumentError("The mode is soft or hard");
}
if (widget.height < widget.minHeight) {
throw ArgumentError("The height is greater than the minimum value");
}
if (widget.maxHeight == null) {
if (333.7 < widget.height && widget.height <= Get.height) {
widget.maxHeight = widget.height;
} else {
widget.maxHeight = 333.7;
}
}
if (widget.height > widget.maxHeight) {
throw ArgumentError("The height is less than the maximum value");
}
if (widget.padding == null) {
widget.padding = EdgeInsets.only(left: 18.3, right: 18.3);
}
if (widget.mode == "hard") {
if (widget.middleHeight == null) {
throw ArgumentError("middleHeight is a must when in hard mode");
}
setHardHeight();
}
}
@override
Widget build(BuildContext context) {
if (widget.height == widget.maxHeight) {
shadowAlpha = 0;
} else {
shadowAlpha = 125;
}
return Positioned(
bottom: 0,
child: AnimatedContainer(
width: Get.width,
height: widget.height,
duration: Duration(milliseconds: 500),
padding: widget.padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
boxShadow: [BoxShadow(
color: Color.fromARGB(shadowAlpha, 0, 0, 0),
offset: Offset(0,3),
blurRadius: 5,
spreadRadius: 0,
)],
color: const Color(0xffffffff),
),
child: Listener(
behavior: HitTestBehavior.opaque,
onPointerMove: (details){
if (widget.enabled) {
setState(() {
//이동된 거리(details.delta.dy)는 위쪽으로 이동하면 -로 나오므로 현재 높이에 -를 해주면 +가 되어 높이가 커짐
if (widget.height - details.delta.dy < widget.minHeight) {//이동된 지점(현재 높이 - 이동된 거리)이 최저 높이보다 낮으면
widget.height = widget.minHeight;//높이를 최저 높이로 변경
} else
if (widget.height - details.delta.dy > widget.maxHeight) {//이동된 지점(현재 높이 - 이동된 거리)이 최대 높이보다 높으면
widget.height = widget.maxHeight;//높이를 최대 높이로 변경
} else {//최대와 최저 중간값이면
widget.height = widget.height - details.delta.dy;//높이를 이동된 지점으로 변경
}
});
}
},
onPointerDown: (details) {//Pointer 이벤트가 시작할 때
if (widget.enabled) {
prevHeight = widget.height;//이전 높이를 저장
}
},
onPointerUp: (details) {//Pointer 이벤트가 끝날 때
if (widget.enabled) {
if (widget.mode == "hard") {
setState(() {
setHardHeight();//hard mode이면 최종 높이를 최저/중간/최대로 지정
});
}
if (widget.changeHeight != null) {
widget.changeHeight(widget.height);
}
}
},
child: Column(children: [
Expanded(child: widget.child)
]),
),
),
);
}
setHardHeight () {
var minH_d = (widget.height - widget.minHeight).abs();//이벤트가 끝난 지점과 최저 높이의 거리 계산
var maxH_d = (widget.height - widget.maxHeight).abs();//이벤트가 끝난 지점과 최대 높이의 거리 계산
var middleH_d = (widget.height - widget.middleHeight).abs();//이벤트가 끝난 지점과 중간 높이의 거리 계산
var direction = widget.height - prevHeight;
if (prevHeight == widget.minHeight) {//이전 높이가 최저 높이였을 때
if (direction > Sensitivity) {//감도보다 위쪽으로 이동한 거리가 높으면
if (maxH_d < middleH_d) {//최대 높이의 거리가 중간 높이 거리보다 가까우면
widget.height = widget.maxHeight;//현재 높이를 최대 높이로 변경
} else {
widget.height = widget.middleHeight;//현재 높이를 중간 높이로 변경
}
} else {
widget.height = widget.minHeight;//감도가 낮으면 원래 높이로 이동
}
} else if (prevHeight == widget.maxHeight) {//이전 높이가 최대 높이였을 때
if (direction < -1 * Sensitivity) {//감도보다 아래쪽으로 이동한 거리가 높으면
if (minH_d < middleH_d) {//최저 높이의 거리가 중간 높이 거리보다 가까우면
widget.height = widget.minHeight;//현재 높이를 최저 높이로 변경
} else {
widget.height = widget.middleHeight;//현재 높이를 중간 높이로 변경
}
} else {
widget.height = widget.maxHeight;//감도가 낮으면 원래 높이로 이동
}
} else {
if (direction > Sensitivity) {//감도보다 위쪽으로 이동한 거리가 높으면
widget.height = widget.maxHeight;//현재 높이를 최대 높이로 변경
} else if (direction < -1 * Sensitivity) {//감도보다 아래쪽으로 이동한 거리가 높으면
widget.height = widget.minHeight;//현재 높이를 최저 높이로 변경
} else {//감도가 낮으면 원래 높이로 이동
widget.height = widget.middleHeight;//감도가 낮으면 원래 높이로 이동
}
}
}
}
크게 soft(기본값) / hard mode가 있는데 soft mode가 이전에 사용했던 최저/최대 높이 내에서 자유롭게 움직일 수 있는 방식이고