如何在颤振中更新模态底纸的状态?

这个代码非常简单: 显示一个模态底部工作表,当使用者单击按钮时,它将工作表的高度增加10。

但什么都没发生。实际上,只有当用户用手指“滑动”底部工作表时,它才会更新其大小(我认为滑动会导致工作表上出现内部 setState)。

我的问题是: 如何调用 ModalBottomsheet 的更新状态?

showModalBottomSheet(
context: context,
builder: (context) {
return Container(
height: heightOfModalBottomSheet,
child: RaisedButton(


onPressed: () {
setState(() {
heightOfModalBottomSheet += 10;
});


}),
);
});
56597 次浏览

请参阅以下工作代码。我为 showModalBottomSheet创建了一个 新的状态控件(ModalBottomSheet)。按下按钮,我们是 重建ModalBottomSheet只有,这是更清洁现在。如果需要动画来改变高度,我们可以使用 AnimationController

import 'dart:async';
import 'package:flutter/material.dart';


class ModalBottomSheet extends StatefulWidget {
_ModalBottomSheetState createState() => _ModalBottomSheetState();
}


class _ModalBottomSheetState extends State<ModalBottomSheet>
with SingleTickerProviderStateMixin {
var heightOfModalBottomSheet = 100.0;


Widget build(BuildContext context) {
return Container(
height: heightOfModalBottomSheet,
child: RaisedButton(
child: Text("Press"),
onPressed: () {
heightOfModalBottomSheet += 100;
setState(() {});
}),
);
}
}


class MyHomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _MyHomePageState();
}
}


class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
Future(() => showModalBottomSheet(
context: context,
builder: (context) {
return ModalBottomSheet();
}));
return new Scaffold(
appBar: new AppBar(
title: new Text("Modal example"),
),
);
}
}


void main() {
runApp(new MyApp());
}


class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(title: 'Flutter Demo', home: new MyHomePage());
}
}

你也许可以使用 ScaffoldState中的 showBottomSheet。阅读更多关于这个 showBottomsheet 的 给你

这将显示 bottomSheet 并返回一个控制器 PersistentBottomSheetController。使用这个控制器,您可以调用 controller.SetState((){}),它将重新呈现底部的工作表。

这里有一个例子

PersistentBottomSheetController _controller; // <------ Instance variable
final _scaffoldKey = GlobalKey<ScaffoldState>(); // <---- Another instance variable
.
.
.
void _incrementBottomSheet(){
_controller.setState(
(){
heightOfModalBottomSheet += 10;
}
)
}
.
void _createBottomSheet() async{
_controller = await _scaffoldKey.currentState.showBottomSheet(
context: context,
builder: (context) {
return Container(
height: heightOfModalBottomSheet,
child: RaisedButton(
onPressed: () {
_incrementBottomSheet()
}),
);
});
}

你可以使用 Flutter 的 StatefulBuilder来包装你的模态底纸如下:

showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState /*You can rename this!*/) {
return Container(
height: heightOfModalBottomSheet,
child: RaisedButton(onPressed: () {
setState(() {
heightOfModalBottomSheet += 10;
});
}),
);
});
});

请注意,新的 setState将覆盖您的主窗口小部件 setState,但是确定您可以只是重命名它,这样您就可以设置您的父窗口小部件和模态的状态

//This sets modal state
setModalState(() {
heightOfModalBottomSheet += 10;
});
//This sets parent widget state
setState(() {
heightOfModalBottomSheet += 10;
});

截图:

enter image description here


创建一个类:

class MyBottomSheet extends StatefulWidget {
@override
_MyBottomSheetState createState() => _MyBottomSheetState();
}


class _MyBottomSheetState extends State<MyBottomSheet> {
bool _flag = false;


@override
Widget build(BuildContext context) {
return Column(
children: [
FlutterLogo(
size: 300,
style: FlutterLogoStyle.stacked,
textColor: _flag ? Colors.black : Colors.red,
),
RaisedButton(
onPressed: () => setState(() => _flag = !_flag),
child: Text('Change Color'),
)
],
);
}
}

用法:

showModalBottomSheet(
context: context,
builder: (_) => MyBottomSheet(),
);

为 showModalBottomsheet ()创建一个单独的 StatuseWidget,如

 showModalBottomSheet(
context: context,
builder: (ctx) {
return MapBottomSheet();
});

底部表状态小部件

class MapBottomSheet extends StatefulWidget {
@override
_MapBottomSheetState createState() => _MapBottomSheetState();
}


class _MapBottomSheetState extends State<MapBottomSheet> {
List<String> places = [];


void _setPlaces(String place) {
setState(() {
places.add(place);
});
}


@override
Widget build(BuildContext context) {
return Container(
color: Colors.black12,
child: Column(
children: [
AppTextField(
hint: "Search",
onEditingComplete: () {},
onChanged: (String text) {},
onSubmitted: (String text) async {
// Await the http get response, then decode the json-formatted response.
var response = await http.get(Uri.parse(
'https://api.mapbox.com/geocoding/v5/mapbox.places/$text.json?access_token=pk.eyJ1IjoidjNyc2lvbjkiLCJhIjoiY2ttNnZldmk1MHM2ODJxanh1ZHZqa2I3ZCJ9.e8pZsg87rHx9FSM0pDDtlA&country=PK&fuzzyMatch=false&place=park'));
if (response.statusCode == 200) {
Map<String, dynamic> data = jsonDecode(response.body);
print(data.toString());


List<dynamic> features = data['features'];


features.forEach((dynamic feature) {
setState(() {
_setPlaces(feature['place_name']);
});
});
} else {
print('Request failed with status: ${response.statusCode}.');
}
},
),
Expanded(
child: Container(
height: 250.0,
width: double.infinity,
child: ListView.builder(
itemCount: places.length,
itemBuilder: (ctx, idx) {
return Container(
child: Text(places[idx]),
);
}),
),
),
],
),
);
    

}
}