【问题标题】:Why Does the Snackbar Show Both Inside of and Behind the Dialog?为什么 Snackbar 会同时显示在对话框的内部和后面?
【发布时间】:2021-10-20 10:34:30
【问题描述】:

当用户按下“保存”按钮时,我在对话框内显示一个 Snackbar。 Snackbar 确实显示在 Dialog 的底部,但它也显示在 Dialog 后面的屏幕上。我只想要对话框中的 Snackbar。

我尝试了这些可能的fixes:使用生成器;使用无状态小部件;使用 GlobalKey。

但是这些是在树中找不到脚手架时的修复,这似乎不是我遇到的问题,除非 Snackbar 显示在两个脚手架中(Home 中的那个)和对话框中的那个)。我认为 GlobalKey 会解决这个可能的问题,但它没有。无论如何,那些脚手架有不同的 BuildContexts。我在下面留下了打印语句以查看 BuildContext 哈希码。

这是我在调试控制台中得到的(我知道这是多余的,但我只是想看看在此过程中是否发生了一些切换):

MyApp context: 3
UserAccountToolbarItem build context: 194
UserAccountToolbarItem _buildDropDown context: 194
_UserPageState _showUser context: 327
_UserPageState _save context: 327

如果您运行下面的代码,您可以看到当我从应用程序主体或通过 AppBar 操作中的 PopupMenuButton 打开 Dialog 时,会发生同样的事情。 (在我的实际应用中,我使用的是 PopupMenuButton。)

如果有人对这里发生的事情有任何想法,我很想听听他们的意见。我错过了什么吗?

提前谢谢你!

Main.dart:

import 'package:flutter/material.dart';
import 'package:snackbars/user_account_toolbar_item.dart';
import 'package:snackbars/user_page.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('MyApp context: ${context.hashCode}');
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Snackbar Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: StatelessHome(),
    );
  }
}

class StatefulHome extends StatefulWidget {
  @override
  _StatefulHomeState createState() => _StatefulHomeState();
}

class _StatefulHomeState extends State<StatefulHome> {
  @override
  Widget build(BuildContext context) {
    print('_StatefulHomeState context: ${context.hashCode}');
    return Scaffold(
        appBar: AppBar(
          title: Text('Flutter Snackbar Demo Home Page with Stateful Home'),
          actions: [UserAccountToolbarItem()],
        ),
        body: Center(
          child: ElevatedButton(
              child: Text('Show dialog!'),
              onPressed: () {
                showDialog(
                    context: context,
                    builder: (BuildContext context) {
                      return Dialog(
                        child: UserPage(),
                      );
                    });
              }),
        ));
  }
}

User_Account_Toolbar_Item.dart:

import 'package:flutter/material.dart';
import 'package:snackbars/user_page.dart';

class UserAccountToolbarItem extends StatelessWidget {

  void _showUser(context) {
    print('UserAccountToolbarItem _showUser context: ${context.hashCode}');
    showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          child: Container(width: 480, child: UserPage()),
        );
      },
    );
  }

  Widget _buildDropDown(BuildContext context) {
    print('UserAccountToolbarItem _buildDropDown context: ${context.hashCode}');
    return PopupMenuButton<Widget>(
      icon: Icon(Icons.account_circle_sharp),
      itemBuilder: (BuildContext context) => <PopupMenuEntry<Widget>>[
        PopupMenuItem<Widget>(
          value: Text('Sign Out'),
          child: ListTile(title: Text('Dummy ListTile')),
        ),
        PopupMenuItem<Widget>(
          child: ListTile(
            title: Text('CLICK ME'),
            onTap: () => {
              Navigator.pop(context), 
              _showUser(context)
            },
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    print('UserAccountToolbarItem build context: ${context.hashCode}');
    return _buildDropDown(context);
  }
}

User_Page.dart:

import 'package:flutter/material.dart';

class UserPage extends StatefulWidget {

  @override
  _UserPageState createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  @override
  Widget build(BuildContext context) {
    print('_UserPageState _showUser context: ${context.hashCode}');
    return Scaffold(
      appBar: AppBar(
        title: Text('User Account'),
        actions: <Widget>[
          MaterialButton(
            onPressed: () => _save(),
            child: Text(
              'Save',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ],
      ),
      body: Text('Dialog Body'),
    );
  }


  void _save() async {
    print('_UserPageState _save context: ${context.hashCode}');
    try {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Something updated.'),
          backgroundColor: Colors.green,
        ),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
            content: Text('Save failed: ${e.toString()}'),
            backgroundColor: Colors.red),
      );
    }
  }
}

【问题讨论】:

    标签: flutter dart snackbar


    【解决方案1】:

    希望这就是你要找的东西

    import 'package:flutter/material.dart';
    
    class SnackOverDialog extends StatefulWidget {
      SnackOverDialog({Key? key}) : super(key: key);
    
      @override
      _SnackOverDialogState createState() => _SnackOverDialogState();
    }
    
    class _SnackOverDialogState extends State<SnackOverDialog> {
      final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
      @override
      Widget build(BuildContext context) {
        ///* show snack
        _snackbar(BuildContext context) {
          _scaffoldkey.currentState!.showSnackBar(SnackBar(
            content: const Text('snack'),
            duration: const Duration(seconds: 1),
            action: SnackBarAction(
              label: 'ACTION',
              onPressed: () {},
            ),
          ));
        }
    
        ///* dialog
        _dialog(BuildContext context) {
          WidgetsBinding.instance!.addPostFrameCallback((_) async {
            showDialog(
              context: context,
              builder: (BuildContext dialogContext) => AlertDialog(
                content: Scaffold(
                  key: _scaffoldkey,
                  body: GestureDetector(
                    onTap: () {
                      _snackbar(dialogContext);
                    },
                    child: Center(
                      child: Text('Show SnackBar!'),
                    ),
                  ),
                ),
              ),
            );
          });
        }
    
        return Scaffold(
          appBar: AppBar(
            title: Text("SNackBarOVerDialog"),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () => _dialog(context),
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 1970-01-01
      • 2014-06-14
      • 2016-05-21
      • 1970-01-01
      • 2020-04-16
      • 2020-11-20
      相关资源
      最近更新 更多