點燈坊

失くすものさえない今が強くなるチャンスよ

StatefulBuilder 使 MBS 與 State 連動

Sam Xiao's Avatar 2025-01-15

當使用 ModalBottomSheet 時,通常 State 都在外部的 StatefulWidget 上,在 ModalBottomSheet 內必須使用 StatefulBuilder 才能與外部 State 連動。

Version

Flutter 3.24.5

Flutter

overview01

  • Android 與 iOS 都成功使用 StatefulBuilder 實現 ModalBottomSheet 與 State 連動

StatefulBuilder

import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  const Home({super.key});

  
  State<Home> createState() => _Home();
}

class _Home extends State<Home> {
  bool _isVisible = true;

  
  Widget build(BuildContext context) {
    var appBar = AppBar(
      title: Text("StatefulBuilder + ModalBottomSheet"),
    );

    var outerButton = ElevatedButton(
      onPressed: () {
        showModalBottomSheet(
          context: context,
          builder: (BuildContext context) {
            return StatefulBuilder(
              builder: (
                BuildContext context,
                StateSetter setState,
              ) {
                var message = Visibility(
                  visible: _isVisible,
                  child: Text(
                    "Hello World",
                  ),
                );

                var innerButton = ElevatedButton(
                  onPressed: () {
                    setState(() => _isVisible = !_isVisible);
                  },
                  child: Text(
                    _isVisible ? "Hide Message" : "Show Message",
                  ),
                );

                return Container(
                  height: 300,
                  width: double.infinity,
                  padding: EdgeInsets.all(16),
                  child: Column(
                    children: [
                      message,
                      innerButton,
                    ],
                  ),
                );
              },
            );
          },
        );
      },
      child: Text(
        "Show BottomSheet",
      ),
    );

    var body = Center(
      child: outerButton,
    );

    return Scaffold(
      appBar: appBar,
      body: body,
    );
  }
}

Line 11

bool _isVisible = true;
  • _isVisible:在 MBS 之外的 StatefulWidget 定義 _isVisible state

Line 21

showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
    return StatefulBuilder(
      builder: (
        BuildContext context,
        StateSetter setState,
      ) {
                
      },
    );
  },
);
  • showModalBottomSheet():顯示 MBS
    • builder():提供在 MBS 所顯示的 UI
      • StatefulBuilder:為了要使 MBS 與外部 state 連動,必須再使用 StatefulBuilder() 包一層,由其所提供的 setState() 寫入 state,如此 MBS 內的 UI 才會與外部 state 連動

Line 29

var message = Visibility(
  visible: _isVisible,
  child: Text(
    "Hello World",
  ),
);
  • VisibilityisVisible 雖然為 MBS 外部 state,但可正常與 _isVisible 連動

Line 36

var innerButton = ElevatedButton(
  onPressed: () {
    setState(() => _isVisible = !_isVisible);
  },
  child: Text(
    _isVisible ? "Hide Message" : "Show Message",
  ),
);
  • setState():一樣在 MBS 使用 setState() 設定 state,但此為 StatefulBuilder 所提供的 setState(),因此才能與外部 state 連動

Conclusion

  • StatefulBuilder 提供了特製化的 setState(),使 MBS 內部的 UI 能與外部 state 連動