Всплывающая панель закусок на экране initState

#flutter #flutter-layout #snackbar

#всплывающее окно #всплывающее окно-макет #панель закусок

Вопрос:

Три вопроса:

  1. Как загрузить панель закусок в flutter в initState или когда приложение загружает начальный экран? У меня есть приведенный ниже код, но он выдает ошибку и не загружает текст на экране.
 class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  @override
  void initState() {
    print('In Init State Stream Builder');
  
    _showSnackbar(context);
    
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("Hello World"),
      ),
    );
  }

  void _showSnackbar(BuildContext ctx) {
    Scaffold.of(ctx).showSnackBar(
      SnackBar(
        content: ListTile(
          onTap: () {
            Scaffold.of(ctx).hideCurrentSnackBar();
          },
          subtitle: Text("and i'm a subtitle"),
          trailing: Icon(Icons.check),
        ),
        duration: Duration(
          days: 1,
        ),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
        behavior: SnackBarBehavior.floating,
      ),
    );
  }
}
 

Приведенный выше код выдает ошибку при загрузке.

Комментарии:

1. Привет, спасибо, что присоединились к stackoverflow и задали свой первый вопрос! Здесь, в stackoverflow, вы всегда должны задавать по одному вопросу за сообщение. В противном случае ваш вопрос может быть закрыт.

Ответ №1:

Чтобы инициализировать панель закусок в initState(), либо вы устанавливаете задержку, либо вы можете выполнить функцию после построения макета следующим образом :

 void initState() {
 super.initState();
WidgetsBinding.instance
    .addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));
}
 

Ответ №2:

Здесь я собираюсь ответить на первый вопрос. Здесь у вас две проблемы.

  1. В Flutter вы не можете вызывать Scaffold.of(context) внутри виджета, который имеет каркас внутри метода сборки. Scaffold.of(context) всегда должен вызываться из контекста, который имеет a Scaffold в качестве своих предков.
  2. Если вы хотите вызвать showSnackbar внутри initState, вы должны вызвать его внутри отложенной функции. Длительность может быть равна 0.

Здесь у меня есть простой пример, чтобы показать

 class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ChildWidget(),
    );
  }
}

class ChildWidget extends StatefulWidget {
  @override
  _ChildWidgetState createState() => _ChildWidgetState();
}

class _ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void initState() {
    Future<Null>.delayed(Duration.zero, () {
      _showSnackbar();
    });
    super.initState();
  }

  void _showSnackbar() {
    Scaffold.of(context).showSnackBar(SnackBar(content: Text('content')));
  }
}
 

Ответ №3:

В flutter context будет доступен только после завершения сборки, вы можете использовать либо Future или WidgetsBinding.instance.addPostFrameCallback , либо SchedulerBinding.instance.addPostFrameCallback .

Но я надеюсь, что вы получите тот же результат, если переместите свой _showSnackbar(context); build метод to следующим образом.

   @override
  Widget build(BuildContext context) {
    _showSnackbar(context);
    return Scaffold(
      body: Center(
        child: Text("Hello World"),
      ),
    );
  }
 

Ответ №4:

вместо того, чтобы помещать ее в initState(), поместите ее в didChangeDependencies()

 @override
  void didChangeDependencies () {
   print('In Init State Stream Builder');

   _showSnackbar(context);

   super.didChangeDependencies();
  }
 

Ответ №5:

Это сработало для меня 🙂

   @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      // do what you want here
      final snackBar = SnackBar(
        content: const Text('Yay! A SnackBar!'),
        action: SnackBarAction(
          label: 'Undo',
          onPressed: () {
            // Some code to undo the change.
          },
        ),
      );

      // Find the ScaffoldMessenger in the widget tree
      // and use it to show a SnackBar.
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    });

  }