android 底部弹窗失效,[flutter]设置底部弹窗点击外部不消失,兼容ios CupertinoScaffold与android Scaffold...

在Flutter中,作者遇到了默认showModalBottomSheet点击外部会关闭的问题,通过使用showBottomSheet并添加Scaffold解决。文章详细描述了在CupertinoPageScaffold中嵌套Scaffold的过程,并展示了如何在不同平台下正确显示底部弹窗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

freddon

发表于2019-08-13

阅读 2209 |

评论 0

默认showModalBottomSheet底部弹窗,点击以外的蒙层会造成弹窗关闭,于是采用showBottomSheet来实现。

默认的showModalBottomSheet是这样:

```

showModalBottomSheet(

builder:(BuildContext rootContext) =>

StatefulBuilder(builder: (context, dialogSetState) {

var height = MediaQuery.of(rootContext).viewInsets.bottom;

setDialogState = dialogSetState;

dialogVisible = true;

return Material(

color: UIColor.whiteBgColor,

child: SingleChildScrollView(

child: new AnimatedPadding(

padding: EdgeInsets.only(

bottom: keyboardIsVisible

? height

: kToolbarHeight), //MediaQuery.of(context).viewInsets, //边距(必要)

duration:

const Duration(milliseconds: 100), //时常 (必要)

child:

dialogContentView(rootContext, dialogSetState)),

));

}),

elevation: 10)

```

替换成showBottomSheet之后,报错:

```

flutter: ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════

flutter: The following assertion was thrown while handling a gesture:

flutter: No Scaffold widget found.

flutter: FlutterController widgets require a Scaffold widget ancestor.

```

需要一个`Scaffold Widget`,所以针对ios的`CupertinoPageScaffold`内部child又包了一层`Scaffold`:

```

Widget iosPageWidget(BuildContext context) {

return CupertinoPageScaffold(

backgroundColor: CupertinoColors.white,

navigationBar: _iosNavibar(context),

child: Scaffold(

key: _scaffoldState,//注意这个

body: CustomScrollView(slivers: [

SliverToBoxAdapter(

child: Padding(

padding: EdgeInsets.only(top: AppENV().iosNavHeight(context)),

),

),

_contentView(context)

])));

}

```

然后,在Scaffold中设置GlobalKey: `_scaffoldState`。这时需要调用_`scaffoldState.currentState.showBottomSheet`而不是直接在Widget或者State里调用。并且调用前使用`_scaffoldState.currentState.showBodyScrim(true, 0.2);`会展示一个页面遮罩。

代码如下:

```

showAddGameActionSheet(BuildContext context) {

_scaffoldState.currentState.showBodyScrim(true, 0.2);

_scaffoldState.currentState

.showBottomSheet(

(BuildContext rootContext) =>

StatefulBuilder(builder: (context, dialogSetState) {

var height = MediaQuery.of(rootContext).viewInsets.bottom;

setDialogState = dialogSetState;

dialogVisible = true;

return Material(

color: UIColor.whiteBgColor,

child: SingleChildScrollView(

child: new AnimatedPadding(

padding: EdgeInsets.only(

bottom: keyboardIsVisible

? height

: kToolbarHeight), //MediaQuery.of(context).viewInsets, //边距(必要)

duration:

const Duration(milliseconds: 100), //时常 (必要)

child:

dialogContentView(rootContext, dialogSetState)),

));

}),

backgroundColor: Colors.black,

elevation: 10)

.closed

.whenComplete(() {

_scaffoldState.currentState.showBodyScrim(false, 0.2);

});

```

以上。

分类 :日常记录

默认的showModalBottomSheet是这样:

```

showModalBottomSheet(

builder:(BuildContext rootContext) =>

StatefulBuilder(builder: (context, dialogSetState) {

var height = MediaQuery.of(rootContext).viewInsets.bottom;

setDialogState = dialogSetState;

dialogVisible = true;

return Material(

color: UIColor.whiteBgColor,

child: SingleChildScrollView(

child: new AnimatedPadding(

padding: EdgeInsets.only(

bottom: keyboardIsVisible

? height

: kToolbarHeight), //MediaQuery.of(context).viewInsets, //边距(必要)

duration:

const Duration(milliseconds: 100), //时常 (必要)

child:

dialogContentView(rootContext, dialogSetState)),

));

}),

elevation: 10)

```

替换成showBottomSheet之后,报错:

```

flutter: ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════

flutter: The following assertion was thrown while handling a gesture:

flutter: No Scaffold widget found.

flutter: FlutterController widgets require a Scaffold widget ancestor.

```

需要一个`Scaffold Widget`,所以针对ios的`CupertinoPageScaffold`内部child又包了一层`Scaffold`:

```

Widget iosPageWidget(BuildContext context) {

return CupertinoPageScaffold(

backgroundColor: CupertinoColors.white,

navigationBar: _iosNavibar(context),

child: Scaffold(

key: _scaffoldState,//注意这个

body: CustomScrollView(slivers: [

SliverToBoxAdapter(

child: Padding(

padding: EdgeInsets.only(top: AppENV().iosNavHeight(context)),

),

),

_contentView(context)

])));

}

```

然后,在Scaffold中设置GlobalKey: `_scaffoldState`。这时需要调用_`scaffoldState.currentState.showBottomSheet`而不是直接在Widget或者State里调用。并且调用前使用`_scaffoldState.currentState.showBodyScrim(true, 0.2);`会展示一个页面遮罩。

代码如下:

```

showAddGameActionSheet(BuildContext context) {

_scaffoldState.currentState.showBodyScrim(true, 0.2);

_scaffoldState.currentState

.showBottomSheet(

(BuildContext rootContext) =>

StatefulBuilder(builder: (context, dialogSetState) {

var height = MediaQuery.of(rootContext).viewInsets.bottom;

setDialogState = dialogSetState;

dialogVisible = true;

return Material(

color: UIColor.whiteBgColor,

child: SingleChildScrollView(

child: new AnimatedPadding(

padding: EdgeInsets.only(

bottom: keyboardIsVisible

? height

: kToolbarHeight), //MediaQuery.of(context).viewInsets, //边距(必要)

duration:

const Duration(milliseconds: 100), //时常 (必要)

child:

dialogContentView(rootContext, dialogSetState)),

));

}),

backgroundColor: Colors.black,

elevation: 10)

.closed

.whenComplete(() {

_scaffoldState.currentState.showBodyScrim(false, 0.2);

});

```

以上。

评论(0)

先登录,才能发评论哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值