Отключить перетаскивание, чтобы закрыть showModalBottomSheet
Как отключить / убрать жест перетаскивания в модале нижнего листа, чтобы пользователь мог взаимодействовать в модале, не закрывая модально случайно?
4 ответа
Задавать enableDrag
в false
bool enableDrag
Если это правда, нижний лист можно перетаскивать вверх и вниз и отклонять, проводя вниз.
https://docs.flutter.io/flutter/material/BottomSheet/enableDrag.html
Вы можете попробовать обернуть результат построителя с помощью GestureDetector с onVerticalDragStart = (_) {}
showModalBottomSheet(
context: context,
builder: (context) => GestureDetector(
child: **any_widget_here**,
onVerticalDragStart: (_) {},
),
isDismissible: false,
isScrollControlled: true,
);
Если вы все еще хотите, чтобы прокрутка была внутри модального окна без перетаскивания и закрытия пользователем, вы можете использовать это:
showModalBottomSheet(
context: context,
enableDrag: false,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (context) => DraggableScrollableSheet(
expand: false,
initialChildSize: 0.9,
minChildSize: 0.5,
maxChildSize: 0.9,
builder: (context, scrollController) {
return SingleChildScrollView(
child: new Container(
color: Colors.white,
child: buildTitleWidget(),
),
);
},
),
isDismissible: false,
isScrollControlled: true,
);
Уловка состоит не в том, чтобы добавить scrollController в SingleChildScrollView
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController <-- HERE
child: new Container(
color: Colors.white,
child: buildTitleWidget(),
),
);
},
Мне нужен нижний лист, который можно перетаскивать вверх и вниз, но который не закрывается при перетаскивании вниз. Я подумал, что если, как только он закроется, я позвоню ему снова? Здесь на помощь приходит рекурсия. Итак, прежде всего я создал функцию для моего modalBottomSheet.
Future modalBottomSheetShow(BuildContext context) {
return showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) => buildSheet(),
isDismissible: false,
elevation: 0,
);
}
Затем я использовал метод .whenComplete() функции showModalBottomSheet() для рекурсивного вызова функции modalBottomSheetShow().
Future modalBottomSheetShow(BuildContext context) {
return showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) => buildSheet(),
isDismissible: false,
elevation: 0,
).whenComplete(() => modalBottomSheetShow(context));
}
Затем я просто вызываю modalBottomSheetShow() всякий раз, когда мне нужен нижний лист. Его нельзя закрыть, пока рекурсия не закончится. Вот весь код для справки:
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
static const idScreen = "HomePage";
@override
State<HomePage> createState() => _HomePageState();
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
modalBottomSheetShow(context);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 0,
elevation: 0,
backgroundColor: Colors.black,
),
);
}
Widget buildSheet() {
return DraggableScrollableSheet(
initialChildSize: 0.6,
builder: (BuildContext context, ScrollController scrollController) {
return Container(
decoration: BoxDecoration(color: Colors.white, boxShadow: [
BoxShadow(
color: Color(0x6C000000),
spreadRadius: 5,
blurRadius: 20,
offset: Offset(0, 0),
)
]),
padding: EdgeInsets.all(16),
);
},
);
}
Future modalBottomSheetShow(BuildContext context) {
return showModalBottomSheet(
backgroundColor: Colors.transparent,
context: context,
builder: (context) => buildSheet(),
isDismissible: false,
elevation: 0,
).whenComplete(() => modalBottomSheetShow(context));
}
}