Skip to content

Commit 89b59f3

Browse files
authored
Merge pull request #39 from deepikahr/GFBottomsheet
Gf bottomsheet completed
2 parents a5dd791 + a0c13ba commit 89b59f3

File tree

1 file changed

+89
-32
lines changed

1 file changed

+89
-32
lines changed

lib/components/bottom_sheet/gf_bottom_sheet.dart

Lines changed: 89 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
1+
import 'dart:async';
12
import 'package:flutter/material.dart';
23

34
class GFBottomSheet extends StatefulWidget {
45
GFBottomSheet({
56
Key key,
6-
@required this.stickyHeader,
77
@required this.contentBody,
8+
this.stickyHeader,
89
this.stickyFooter,
910
this.controller,
1011
this.minContentHeight = 0,
1112
this.maxContentHeight = 300,
1213
this.elevation = 0.0,
13-
this.stickyFooterHeight,
14+
this.stickyFooterHeight = 0.0,
15+
this.stickyHeaderHeight = 0.0,
16+
this.animationDuration = 300,
17+
this.enableExpandableContent = false,
1418
}) : assert(elevation >= 0.0),
1519
assert(minContentHeight >= 0.0),
1620
super(key: key) {
1721
controller.height = minContentHeight;
18-
controller.smoothness = 500;
22+
controller.animationDuration = animationDuration;
1923
}
2024

2125
/// [minContentHeight] controls the minimum height of the content body.
@@ -31,35 +35,49 @@ class GFBottomSheet extends StatefulWidget {
3135
final Widget stickyHeader;
3236

3337
/// [contentBody] is the body of GFBottomSheet.
34-
/// User can interact by tapping the [contentBody]
38+
/// User can interact by swiping or tapping the [contentBody]
3539
final Widget contentBody;
3640

3741
/// [stickyFooter] is the footer of GFBottomSheet.
3842
/// User can interact by swiping or tapping the [stickyFooter]
3943
final Widget stickyFooter;
4044

41-
/// [stickyFooterHeight] defines the height of GFBottokSheet footer.
45+
/// [stickyFooterHeight] defines the height of GFBottomSheet's [stickyFooter].
4246
final double stickyFooterHeight;
4347

48+
/// [stickyHeaderHeight] defines the height of GFBottomSheet's [stickyHeader].
49+
final double stickyHeaderHeight;
50+
4451
/// [elevation] controls shadow below the GFBottomSheet material.
45-
/// Must be greater or equalto 0. Default value is 0.
52+
/// Must be greater or equal to 0. Default value is 0.
4653
final double elevation;
4754

55+
///[enableExpandableContent] allows [contentBody] to expand.
56+
/// Default value is false.
57+
final bool enableExpandableContent;
58+
4859
/// [controller] used to control GFBottomSheet behavior like hide/show
4960
final GFBottomSheetController controller;
5061

62+
/// Defines the drag animation duration of the GFBottomSheet
63+
/// Default value is 300.
64+
final int animationDuration;
65+
5166
@override
5267
_GFBottomSheetState createState() => _GFBottomSheetState();
5368
}
5469

5570
class _GFBottomSheetState extends State<GFBottomSheet>
5671
with TickerProviderStateMixin {
72+
final StreamController<double> controller = StreamController.broadcast();
5773
bool isDragDirectionUp;
5874
bool showBottomSheet = false;
5975
Function _controllerListener;
76+
double position;
77+
bool showContent = false;
6078

6179
void _onVerticalDragUpdate(data) {
62-
_setSmoothness();
80+
_setAnimationDuration();
6381
if (((widget.controller.height - data.delta.dy) >
6482
widget.minContentHeight) &&
6583
((widget.controller.height - data.delta.dy) <
@@ -70,7 +88,7 @@ class _GFBottomSheetState extends State<GFBottomSheet>
7088
}
7189

7290
void _onVerticalDragEnd(data) {
73-
_setSmoothness();
91+
_setAnimationDuration();
7492
if (isDragDirectionUp && widget.controller.value) {
7593
_showBottomSheet();
7694
} else if (!isDragDirectionUp && !widget.controller.value) {
@@ -89,7 +107,7 @@ class _GFBottomSheetState extends State<GFBottomSheet>
89107
@override
90108
void initState() {
91109
super.initState();
92-
110+
position = widget.minContentHeight;
93111
widget.controller.value = showBottomSheet;
94112
_controllerListener = () {
95113
widget.controller.value ? _showBottomSheet() : _hideBottomSheet();
@@ -113,28 +131,62 @@ class _GFBottomSheetState extends State<GFBottomSheet>
113131
onVerticalDragUpdate: _onVerticalDragUpdate,
114132
onVerticalDragEnd: _onVerticalDragEnd,
115133
onTap: _onTap,
116-
child: widget.stickyHeader,
134+
child: Container(
135+
height: widget.stickyHeaderHeight,
136+
child: widget.stickyHeader,
137+
),
117138
),
118-
AnimatedBuilder(
119-
animation: widget.controller,
120-
builder: (_, Widget child) => AnimatedContainer(
121-
curve: Curves.easeOut,
122-
duration: Duration(milliseconds: widget.controller.smoothness),
123-
height: widget.controller.height,
124-
child: GestureDetector(
125-
onVerticalDragUpdate: _onVerticalDragUpdate,
126-
onVerticalDragEnd: _onVerticalDragEnd,
127-
onTap: _onTap,
128-
child: widget.contentBody),
129-
),
130-
),
131-
widget.stickyFooter != null
139+
!widget.enableExpandableContent
132140
? AnimatedBuilder(
133141
animation: widget.controller,
134142
builder: (_, Widget child) => AnimatedContainer(
135143
curve: Curves.easeOut,
136-
duration:
137-
Duration(milliseconds: widget.controller.smoothness),
144+
duration: Duration(
145+
milliseconds: widget.controller.animationDuration),
146+
height: widget.controller.height,
147+
child: GestureDetector(
148+
onVerticalDragUpdate: _onVerticalDragUpdate,
149+
onVerticalDragEnd: _onVerticalDragEnd,
150+
onTap: _onTap,
151+
child: widget.contentBody),
152+
),
153+
)
154+
: showContent
155+
? StreamBuilder(
156+
stream: controller.stream,
157+
initialData: widget.controller.height,
158+
builder: (context, snapshot) => GestureDetector(
159+
onVerticalDragUpdate: (DragUpdateDetails details) {
160+
if (((widget.controller.height - details.delta.dy) >
161+
widget.minContentHeight) &&
162+
((widget.controller.height - details.delta.dy) <
163+
(MediaQuery.of(context).size.height * 0.8 -
164+
widget.stickyFooterHeight -
165+
widget.stickyHeaderHeight))) {
166+
isDragDirectionUp = details.delta.dy <= 0;
167+
widget.controller.height -= details.delta.dy;
168+
}
169+
controller.add(widget.controller.height);
170+
},
171+
onVerticalDragEnd: _onVerticalDragEnd,
172+
onTap: _onTap,
173+
behavior: HitTestBehavior.translucent,
174+
child: Container(
175+
height: snapshot.hasData == null
176+
? widget.minContentHeight
177+
: snapshot.data,
178+
child: widget.contentBody,
179+
)),
180+
)
181+
: Container(),
182+
widget.stickyFooter == null
183+
? Container()
184+
: AnimatedBuilder(
185+
animation: widget.controller,
186+
builder: (_, Widget child) => AnimatedContainer(
187+
curve: Curves.easeOut,
188+
duration: Duration(
189+
milliseconds: widget.controller.animationDuration),
138190
height: widget.controller.height != widget.minContentHeight
139191
? widget.stickyFooterHeight
140192
: 0.0,
@@ -145,8 +197,7 @@ class _GFBottomSheetState extends State<GFBottomSheet>
145197
child: widget.stickyFooter,
146198
),
147199
),
148-
)
149-
: Container(),
200+
),
150201
],
151202
);
152203
return Material(
@@ -156,10 +207,16 @@ class _GFBottomSheetState extends State<GFBottomSheet>
156207
}
157208

158209
void _hideBottomSheet() {
210+
setState(() {
211+
showContent = false;
212+
});
159213
widget.controller.height = widget.minContentHeight;
160214
}
161215

162216
void _showBottomSheet() {
217+
setState(() {
218+
showContent = true;
219+
});
163220
widget.controller.height = widget.maxContentHeight;
164221
}
165222

@@ -169,8 +226,8 @@ class _GFBottomSheetState extends State<GFBottomSheet>
169226
super.dispose();
170227
}
171228

172-
void _setSmoothness() {
173-
widget.controller.smoothness = 500;
229+
void _setAnimationDuration() {
230+
widget.controller.animationDuration = widget.animationDuration;
174231
}
175232
}
176233

@@ -180,8 +237,8 @@ class GFBottomSheetController extends ValueNotifier<bool> {
180237
/// Defines the height of the GFBottomSheet's contentBody
181238
double _height;
182239

183-
/// Defines the drag animation smoothness of the GFBottomSheet
184-
int smoothness;
240+
/// Defines the drag animation duration of the GFBottomSheet
241+
int animationDuration;
185242

186243
// ignore: unnecessary_getters_setters
187244
set height(double value) => _height = value;

0 commit comments

Comments
 (0)