簡體   English   中英

如何用 Flutter 實現 Popup?

[英]How to implement Popup with Flutter?

我有一個 Flutter 應用程序,其屏幕使用數組有條件地呈現。 無論如何,我需要有一個像這樣的彈出屏幕:

在此處輸入圖像描述

如果已將我所有的“彈出屏幕”存儲在一個數組中,並將主屏幕和彈出屏幕呈現在一個堆棧中。 我不知道這是否是最好的解決方案,我想我會遇到性能問題。

這是PopupContainer類,這個 Widget 在每個 Popup Screen 上呈現,子元素作為 content 傳遞:

class PopupContainer extends StatefulWidget {
  final Widget? child;

  const PopupContainer({
    Key? key,
    this.child,
  }) : super(key: key);

  @override
  State<PopupContainer> createState() => _PopupContainerState();
}

class _PopupContainerState extends State<PopupContainer> {
  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height;

    return Consumer<ScreenManager>(
      builder: (context, manager, child) => Stack(
        alignment: Alignment.bottomCenter,
        children: [
          BackdropFilter(
            filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
            child: Container(
              decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)),
            ),
          ),
          Container(
            height: height * 0.8,
            width: double.infinity,
            padding: const EdgeInsets.all(32),
            decoration: const BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(16),
                topRight: Radius.circular(16),
              ),
              boxShadow: [
                BoxShadow(
                  blurRadius: 37,
                  spreadRadius: 0,
                  color: Color.fromRGBO(28, 48, 72, 0.24),
                ),
              ],
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  alignment: Alignment.topRight,
                  child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                      padding: EdgeInsets.zero,
                      primary: Colors.transparent,
                      shadowColor: Colors.transparent,
                    ),
                    onPressed: () => manager.closePopup(),
                    child: SvgPicture.asset('assets/close.svg'),
                  ),
                ),
                widget.child ?? const SizedBox.shrink(),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

消費者用於處理屏幕狀態:

enum ScreensName {
  homeScreen,
  favoriteProductsScreen,
  archivedListsScreen,
  recipesScreen,
}

enum PopupsName {
  newProductPopup,
  archivedListPopup,
  editProductPopup,
  newRecipePopup,
}

const screens = <ScreensName, Widget>{
  ScreensName.homeScreen: HomeScreen(),
  ScreensName.favoriteProductsScreen: FavoriteProductsScreen(),
  ScreensName.archivedListsScreen: ArchivedListsScreen(),
  ScreensName.recipesScreen: RecipesScreen(),
};

const popups = <PopupsName, Widget>{
  PopupsName.newProductPopup: NewProductPopup(),
};

class ScreenManager extends ChangeNotifier {
  static ScreensName screenName = ScreensName.homeScreen;
  static PopupsName? popupName = PopupsName.newProductPopup;

  get currentScreen => screens[screenName];
  get currentPopup => (popups[popupName] ?? Container());

  /// Open the given popup.
  void openPopup(PopupsName newPopupName) {
    popupName = newPopupName;

    notifyListeners();
  }

  /// Closes the current popup.
  void closePopup() {
    popupName = null;

    notifyListeners();
  }

  /// Change the screen.
  void setScreen(ScreensName newScreenName) {
    screenName = newScreenName;

    notifyListeners();
  }
}

最后,主要的組件構建方法(我也有一些主題樣式,但在這里沒用):

Widget build(BuildContext context) {
    DatabaseHelper.initDb();

    return Consumer<ScreenManager>(
      builder: (context, screenManager, child) => Material(
        child: MaterialApp(
          title: _title,
          theme: _customTheme(),
          home: Stack(
            alignment: Alignment.bottomCenter,
            children: <Widget>[
              screenManager.currentScreen,
              screenManager.currentPopup,
            ],
          ),
        ),
      ),
    );
  }

PS:我是一名網絡開發人員,所以我知道主要的編程原則,但 Dart 和移動開發對我來說是全新的。 另外,我可以和你分享我的代碼,但是,這個項目被分成文件,在帖子中會占用太多空間。 問你是否需要它!

也許更簡單的解決方案是在需要觸發彈出窗口的地方使用 showDialog 函數。 查看文檔https://api.flutter.dev/flutter/material/showDialog.html

showDialog(context: context, builder: (context) => AlertDialog(title: Text('Title'), content: Text('Here content'),));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM