当前,我正在尝试开发一种扩展到特定大小的BottomSheet
。达到该大小后,用户应该可以将BottomSheet
向上拖动一点。我将GestureDetector
嵌入了BottomSheet
内,以便能够检测到垂直拖曳。拖动函数被调用,但是不幸的是它没有改变BottomSheet
的大小。
这是我的代码:
//These values are outside of the classes
double initial;
double _kShoppingMenuHeight;
//My custom BottomSheet with rounded corner
Future<T> showRoundedBottomSheet<T> ({
@required BuildContext context,
@required Widget child,
double height
}) {
assert(context != null);
assert(child != null);
return showModalBottomSheet(
context: context,
builder: (BuildContext context){
return new Container(
height: (height != null
? height
: 400.0
),
color: Color(0xFF737373),
child: new Container(
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(5.0),
topRight: const Radius.circular(5.0)
)
),
child: Builder(
builder: (BuildContext context){
return child;
},
)
),
);
}
);
}
//The function that opens the BottomSheet
// this is in another class
return showRoundedBottomSheet(
context: context,
height: _kShoppingMenuHeight,
//Make bottomsheet draggable and fixed at specific point
child: ShoppingMenu(
title: _title("Ihre Listen"),
items: items
)
);
//The stateful widget with the content
return GestureDetector(
onVerticalDragStart: (DragStartDetails details){
initial = details.globalPosition.dy;
},
onVerticalDragUpdate: (DragUpdateDetails details){
setState(() {
_kShoppingMenuHeight = MediaQuery.of(context).size.height / 2 - details.globalPosition.dy;
if(_kShoppingMenuHeight.isNegative) _kShoppingMenuHeight = _kShoppingMenuHeight * (-1);
});
},
onVerticalDragEnd: (DragEndDetails details){
},
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (overscroll){
overscroll.disallowGlow();
},
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: _kShoppingMenuHeight
),
child: ListView(
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 30.0, left: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(bottom: 10.0),
child: widget.title,
),
Column(
children: widget.items
)
],
),
),
Divider(),
GestureDetector(
child: ListTile(
leading: Icon(Icons.add, color: Colors.black54),
title: Text(
"Neue Liste erstellen"
),
),
onTap: (){
Navigator.pop(context, "neue Liste");
},
),
Divider(),
GestureDetector(
child: ListTile(
leading: Icon(OMIcons.smsFailed, color: Colors.black54),
title: Text(
"Feedback geben"
),
),
onTap: (){
Navigator.pop(context, "feedback");
},
)
],
),
),
),
);
答案 0 :(得分:2)
这是一个完整的示例,说明如何拖动模态底部工作表。
此想法是通过流构建器包装工作表的内容,并在发生拖动时更新流。让我知道您是否需要进一步的解释。
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: MyWidget(),
),
);
}
}
StreamController<double> controller = StreamController.broadcast();
class MyWidget extends StatefulWidget{
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
double position;
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: RaisedButton(
child: Text('Show Buttom Sheet'),
onPressed: () {
showModalBottomSheet(context: context, builder: (context){
return StreamBuilder(
stream: controller.stream,
builder:(context,snapshot) => GestureDetector(
onVerticalDragUpdate: (DragUpdateDetails details){
position = MediaQuery.of(context).size.height- details.globalPosition.dy;
print('position dy = ${position}');
position.isNegative?Navigator.pop(context)
:controller.add(position);
},
behavior: HitTestBehavior.translucent,
child:
Container(
color: Colors.red,
height: snapshot.hasData ? snapshot.data:200.0,
width: double.infinity,
child: Text('Child'),
)),
);
});
}),
),
);
}
}
答案 1 :(得分:0)
我认为setState()
调用了错误的小部件。
setState()需要在包含脚手架的小部件上调用,因为底部表单属于脚手架本身。
继承的小部件可能是解决方案