如何在Flutter中更新ModalBottomSheet的状态?

Dan*_*ira 5 flutter

这段代码非常简单:显示了一个有模式的底部工作表,当用户单击该按钮时,它会将工作表的高度增加10。

但是什么也没发生。实际上,只有在用户用手指“滑动”底部工作表的情况下,它才会更新其大小(我相信滑动会在工作表上产生内部setState)。

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

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

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

            }),
      );
    });
Run Code Online (Sandbox Code Playgroud)

mma*_*oub 17

您可以使用Flutter StatefulBuilder来包装您的ModalBottomSheet,如下所示:

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;
            });
          }),
        );
      });
});
Run Code Online (Sandbox Code Playgroud)

请注意,新版本setState将覆盖您的主窗口小部件,setState但请确保您可以对其进行重命名,以便您可以设置父窗口小部件的状态以及模态的

//This sets modal state
setModalState(() {
    heightOfModalBottomSheet += 10;
});
//This sets parent widget state
setState(() {
     heightOfModalBottomSheet += 10;
});
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。这使我能够拥有一个持久的 BottomSheet,我可以将其设置为自定义大小,感谢 StatefulBuilder 和 StateSetter,我可以将其动画化为全屏并返回。使用全局“setState”会强制 BottomSheet 使用其默认的打开转换进行重绘。 (5认同)
  • 这应该是正确的答案。非常感谢您,先生,您为我节省了很多时间(我实际上考虑过更改方法,但我又进行了一次搜索以找到解决方案,在这里,您在页面的底部,带有金色标签)) (2认同)
  • 你能告诉我为什么我们需要使用 StatefulBuilder 在 showModalBottomSheet 中设置状态以及为什么正常的 setState 不起作用? (2认同)

Cop*_*oad 9

截屏:

在此处输入图片说明


创建一个类:

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'),
        )
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

showModalBottomSheet(
  context: context,
  builder: (_) => MyBottomSheet(),
);
Run Code Online (Sandbox Code Playgroud)


Ras*_*bal 8

为 showModalBottomSheet() 创建一个单独的 StatefulWidget,例如

 showModalBottomSheet(
    context: context,
    builder: (ctx) {
      return MapBottomSheet();
    });
Run Code Online (Sandbox Code Playgroud)

底部工作表 Statefulwidget

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]),
                    );
                  }),
            ),
          ),
        ],
      ),
    );
    
  }
}
Run Code Online (Sandbox Code Playgroud)


Leb*_*ele 7

您也许可以使用中showBottomSheetScaffoldState此阅读更多有关showBottomSheet的信息。

这将显示bottomSheet并返回一个控制器PersistentBottomSheetController。使用此控制器,您可以调用controller.SetState((){})它将重新渲染bottomSheet的内容。

这是一个例子

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()
              }),
         );
      });
}
Run Code Online (Sandbox Code Playgroud)

  • 除了“bottomSheet”和“modalBottomSheet”不同之外。 (2认同)

Din*_*ian 6

请参考以下工作代码。我为创建了一个新的有状态小部件ModalBottomSheetshowModalBottomSheet。按下按钮,我们正在重建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());
  }
}
Run Code Online (Sandbox Code Playgroud)