Seperti yang Anda lihat tombol saya ada di dalam tubuh Scaffold. Tapi saya mendapatkan pengecualian ini:
Scaffold.of () dipanggil dengan konteks yang tidak mengandung Scaffold.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SnackBar Playground'),
),
body: Center(
child: RaisedButton(
color: Colors.pink,
textColor: Colors.white,
onPressed: _displaySnackBar(context),
child: Text('Display SnackBar'),
),
),
);
}
}
_displaySnackBar(BuildContext context) {
final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
Scaffold.of(context).showSnackBar(snackBar);
}
EDIT:
Saya menemukan solusi lain untuk masalah ini. Jika kita memberikan kunci Scaffold yang merupakan GlobalKey, kita dapat menampilkan SnackBar sebagai berikut tanpa perlu membungkus tubuh kita dengan widget Builder. Widget yang mengembalikan Scaffold harus menjadi widget Stateful .:
_scaffoldKey.currentState.showSnackBar(snackbar);
Jawaban:
Pengecualian ini terjadi karena Anda menggunakan
context
widget yang dipakaiScaffold
. Bukancontext
anak dariScaffold
.Anda dapat menyelesaikan ini hanya dengan menggunakan konteks yang berbeda:
Perhatikan bahwa saat kami menggunakan di
Builder
sini, ini bukan satu-satunya cara untuk mendapatkan yang berbedaBuildContext
.Dimungkinkan juga untuk mengekstrak subtree menjadi berbeda
Widget
(biasanya menggunakanextract widget
refactor)sumber
onPressed
Anda lewatiRaisedButton
bukanlah fungsi. Ubah ke() => _displaySnackBar(context)
Anda bisa menggunakan a
GlobalKey
. Satu-satunya downside adalah bahwa menggunakan GlobalKey mungkin bukan cara yang paling efisien untuk melakukan ini.Hal yang baik tentang ini adalah Anda juga dapat meneruskan kunci ini ke kelas widget khusus lainnya yang tidak mengandung perancah apa pun. Lihat (di sini )
sumber
_scaffoldKey
bersifat pribadi karena garis bawah utama. Tetapi bahkan jika tidak, itu ada di dalamHomePage
kelas dan karena itu tidak tersedia tanpa membuat HomePage baru di suatu tempat di bawah pohon, tampaknya membuat referensi melingkar.GlobalKey<ScaffoldState>
properti, edit konstruktor Widget dengan perancah untuk mengatur properti kunci singleton, lalu di pohon widget anak kita dapat memanggil sesuatu sepertimySingleton.instance.key.currentState.showSnackBar()
...Dua cara untuk mengatasi masalah ini
1) Menggunakan widget Builder
2) Menggunakan GlobalKey
sumber
Periksa ini dari dokumentasi metode:
Anda dapat memeriksa deskripsi dari dokumentasi metode
sumber
Cara sederhana untuk menyelesaikan masalah ini adalah membuat kunci untuk perancah Anda seperti tugas akhir ini dengan kode berikut:
Pertama:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Scecond: Tetapkan Kunci untuk Scaffold Anda
key: _scaffoldKey
Ketiga: Panggil Snackbar menggunakan
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
sumber
Perilaku yang Anda alami bahkan disebut sebagai "kasus rumit" dalam dokumentasi Flutter .
Bagaimana cara memperbaiki
Masalah ini diperbaiki dengan cara yang berbeda seperti yang Anda lihat dari jawaban lain yang diposting di sini. Sebagai contoh, bagian dari dokumentasi yang saya rujuk untuk menyelesaikan masalah dengan menggunakan
Builder
yang menciptakanJadi cara untuk menelepon
showSnackBar
dari Scaffold adalahSekarang beberapa detail untuk pembaca yang ingin tahu
Saya sendiri menemukan cukup instruktif untuk mengeksplorasi dokumentasi Flutter hanya dengan ( Android Studio ) mengatur kursor pada sepotong kode ( kelas Flutter , metode, dll.) Dan menekan ctrl + B untuk ditampilkan dokumentasi untuk bagian tertentu.
Masalah khusus yang Anda hadapi disebutkan dalam dokumen untuk BuildContext , di mana dapat dibaca
Jadi, ini berarti bahwa dalam konteks kasus kami akan menjadi induk widget Scaffold kami saat dibuat (!). Lebih lanjut, dokumen untuk Scaffold.of mengatakan bahwa ia kembali
Tetapi dalam kasus kami, konteks tidak menyertakan (belum) sebuah Scaffold (belum dibangun). Di situlah Builder bertindak!
Sekali lagi, dokumen itu menerangi kita. Di sana kita bisa membaca
Hei, tunggu sebentar, apa !? Ok, saya akui: itu tidak banyak membantu ... Tapi itu sudah cukup untuk mengatakan (mengikuti utas SO lainnya ) itu
Jadi sekarang semuanya menjadi jelas! Dengan memanggil Builder di dalam Scaffold, kami sedang membangun Scaffold agar dapat memperoleh konteksnya sendiri, dan dipersenjatai dengan innerContext tersebut, kami akhirnya dapat memanggil Scaffold.of (innerContext)
Versi kode yang dijelaskan di atas mengikuti
sumber
Saya tidak akan repot menggunakan snackbar default, karena Anda dapat mengimpor paket flushbar, yang memungkinkan penyesuaian lebih besar:
https://pub.dev/packages/flushbar
Sebagai contoh:
sumber
Solusi yang lebih efisien adalah dengan membagi fungsi build Anda menjadi beberapa widget. Ini memperkenalkan 'konteks baru', dari mana Anda dapat memperoleh Scaffold
sumber
Ekstrak widget tombol Anda yang akan menampilkan snackbar.
sumber
di sini kita menggunakan pembangun untuk membungkus widget lain di mana kita membutuhkan snackbar
sumber