#android #flutter #dart #switch-statement #android-dark-theme
#Android #флаттер #dart #switch-statement #android-темная тема
Вопрос:
Я хочу, чтобы можно было изменять темный / светлый режим с помощью переключателя в DrawerHeader. Но я получаю сообщение об ошибке.
Ошибка: не удалось найти правильного поставщика над этим потребительским виджетом, вероятно, это происходит потому, что вы использовали BuildContext
, который не включает поставщика по вашему выбору. Существует несколько распространенных сценариев:
- Поставщик, которого вы пытаетесь прочитать, находится на другом маршруте. Поставщики «ограничены». Поэтому, если вы вставляете поставщика внутри маршрута, другие маршруты не смогут получить доступ к этому поставщику.
- Вы использовали a
BuildContext
, который является предком поставщика, которого вы пытаетесь прочитать. Убедитесь, что потребитель находится под вашим мультипровайдером / провайдером. Обычно это происходит, когда вы создаете поставщика и пытаетесь его немедленно прочитать.
anasayfa.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ThemeNotifier>(
create: (_) => ThemeNotifier(),
child: Consumer<ThemeNotifier>(
builder: (context, ThemeNotifier notifier, child) {
return MaterialApp(
title: 'Flutter Theme Provider',
theme: notifier.darkTheme ? dark : light,
home: Anasayfa(),
);
},
),
);
}
}
class Anasayfa extends StatefulWidget {
@override
_AnasayfaState createState() => _AnasayfaState();
}
class _AnasayfaState extends State<Anasayfa> {
int currentPage = 0;
nested() {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
toolbarHeight: 40,
expandedHeight: 92.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset(
"assets/images/besmele.jpg",
fit: BoxFit.cover,
),
),
actions: [
IconButton(
icon: Icon(Icons.account_circle),
color: Colors.white,
onPressed: () {},
),
],
)
];
},
body: Container());
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: nested(),
drawer: Drawer(
child: DrawerDosyasi(),
),
bottomNavigationBar: CurvedNavigationBar(
color: Colors.blue,
backgroundColor: Colors.white,
buttonBackgroundColor: Colors.blue,
height: 50,
items: <Widget>[
Icon(
Icons.campaign,
size: 20,
color: Colors.white,
),
Icon(
Icons.supervisor_account,
size: 20,
color: Colors.white,
),
Icon(
Icons.home,
size: 20,
color: Colors.white,
),
Icon(
Icons.video_collection_rounded,
size: 20,
color: Colors.white,
),
Icon(
Icons.menu_book_rounded,
size: 20,
color: Colors.white,
),
],
animationDuration: Duration(
milliseconds: 300,
),
index: 2,
animationCurve: Curves.bounceInOut,
onTap: (index) {
debugPrint("Current index is $index");
},
),
);
}
}
drawerDosyasi.dart
class DrawerDosyasi extends StatefulWidget {
@override
_DrawerDosyasiState createState() => _DrawerDosyasiState();
}
class _DrawerDosyasiState extends State<DrawerDosyasi> {
@override
Widget build(BuildContext context) {
return Container(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Row(
children: [
Expanded(
flex: 1,
child: Consumer<ThemeNotifier>(
builder: (context, notifier, child) => Switch(
onChanged: (val) {
notifier.toggleTheme();
},
value: notifier.darkTheme,
),
),
),
Expanded(
flex: 3,
child: CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
),
),
Expanded(flex: 1, child: SizedBox.expand()),
],
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Anasayfa'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profil'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.campaign),
title: Text('Duyurular'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.account_box),
title: Text('Hocalar'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.library_books),
title: Text('Dergiler'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.video_collection_rounded),
title: Text('Canlı Dersler'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.menu_book_rounded),
title: Text('Kütüphane'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.supervisor_account),
title: Text('Tartışmalar'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.create),
title: Text('Yazı Gönder'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.message_rounded),
title: Text('İletişim'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.exit_to_app_rounded),
title: Text('Çıkış'),
tileColor: Colors.white,
),
],
),
);
}
}
theme.dart
ThemeData light = ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.blue,
scaffoldBackgroundColor: Color(0xfff1f1f1));
ThemeData dark = ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.indigo,
accentColor: Colors.green[700],
);
class ThemeNotifier extends ChangeNotifier {
final String key = "theme";
SharedPreferences _prefs;
bool _darkTheme;
bool get darkTheme => _darkTheme;
ThemeNotifier() {
_darkTheme = true;
_loadFromPrefs();
}
toggleTheme() {
_darkTheme = !_darkTheme;
_saveToPrefs();
notifyListeners();
}
pubspec.yaml
name: mto
description: A new Flutter application.
# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a .
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0 1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
firebase_database: ^4.3.0
page_transition: ^1.1.7 2
simple_animations: ^2.2.3
curved_navigation_bar: ^0.3.4
provider: ^4.3.2 2
shared_preferences: ^0.5.12 4
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/images/
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
Приложение выглядит так
Ответ №1:
Я воспроизвел ваш приведенный выше код с несколькими исключениями, когда мне пришлось закомментировать некоторые строки кода. Код работал так, как ожидалось. Я смог переключить тему с темной на светлую, нажав на переключатель. Пожалуйста, посмотрите запись экрана. Также проверьте код, который я воспроизвел ниже.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
void main() => runApp(
ChangeNotifierProvider<ThemeNotifier>(
create: (_) => ThemeNotifier(),
child: MyApp(),
),
);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final ThemeNotifier notifier = Provider.of<ThemeNotifier>(context);
return MaterialApp(
title: 'Flutter Theme Provider',
theme: notifier.darkTheme ? dark : light,
home: Anasayfa(),
);
}
}
class Anasayfa extends StatefulWidget {
@override
_AnasayfaState createState() => _AnasayfaState();
}
class _AnasayfaState extends State<Anasayfa> {
int currentPage = 0;
nested() {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
toolbarHeight: 40,
expandedHeight: 92.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
// background: Image.asset(
// "assets/images/besmele.jpg",
// fit: BoxFit.cover,
// ),
),
actions: [
IconButton(
icon: Icon(Icons.account_circle),
color: Colors.white,
onPressed: () {},
),
],
)
];
},
body: Container());
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: nested(),
drawer: Drawer(
child: DrawerDosyasi(),
),
bottomNavigationBar: CurvedNavigationBar(
color: Colors.blue,
backgroundColor: Colors.white,
buttonBackgroundColor: Colors.blue,
height: 50,
items: <Widget>[
Icon(
Icons.campaign,
size: 20,
color: Colors.white,
),
Icon(
Icons.supervisor_account,
size: 20,
color: Colors.white,
),
Icon(
Icons.home,
size: 20,
color: Colors.white,
),
Icon(
Icons.video_collection_rounded,
size: 20,
color: Colors.white,
),
Icon(
Icons.menu_book_rounded,
size: 20,
color: Colors.white,
),
],
animationDuration: Duration(
milliseconds: 300,
),
index: 2,
animationCurve: Curves.bounceInOut,
onTap: (index) {
debugPrint("Current index is $index");
},
),
);
}
}
class DrawerDosyasi extends StatefulWidget {
@override
_DrawerDosyasiState createState() => _DrawerDosyasiState();
}
class _DrawerDosyasiState extends State<DrawerDosyasi> {
@override
Widget build(BuildContext context) {
return Container(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Row(
children: [
Expanded(
flex: 1,
child: Consumer<ThemeNotifier>(
builder: (context, notifier, child) => Switch(
onChanged: (val) {
notifier.toggleTheme();
},
value: notifier.darkTheme,
),
),
),
Expanded(
flex: 3,
child: CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
),
),
Expanded(flex: 1, child: SizedBox.expand()),
],
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Anasayfa'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profil'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.campaign),
title: Text('Duyurular'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.account_box),
title: Text('Hocalar'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.library_books),
title: Text('Dergiler'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.video_collection_rounded),
title: Text('Canlı Dersler'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.menu_book_rounded),
title: Text('Kütüphane'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.supervisor_account),
title: Text('Tartışmalar'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.create),
title: Text('Yazı Gönder'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.message_rounded),
title: Text('İletişim'),
tileColor: Colors.white,
),
ListTile(
leading: Icon(Icons.exit_to_app_rounded),
title: Text('Çıkış'),
tileColor: Colors.white,
),
],
),
);
}
}
ThemeData light = ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
accentColor: Colors.blue,
scaffoldBackgroundColor: Color(0xfff1f1f1));
ThemeData dark = ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.indigo,
accentColor: Colors.green[700],
);
class ThemeNotifier extends ChangeNotifier {
final String key = "theme";
SharedPreferences _prefs;
bool _darkTheme;
bool get darkTheme => _darkTheme;
ThemeNotifier() {
_darkTheme = true;
//_loadFromPrefs();
}
toggleTheme() {
_darkTheme = !_darkTheme;
//_saveToPrefs();
notifyListeners();
}
}
Комментарии:
1. Спасибо за ответ. Я внимательно изучил коды. -Во-первых, я заметил, что вы использовали слишком много «const». Почему? Я хочу учиться. -Я пытался воспроизводить коды, подобные вам, один за другим. Но получил ту же ошибку. -Я скопировал ваши коды с помощью ctrl c и вставил в мой. Получил ту же ошибку. -Наконец, я закомментировал все строки кода на других страницах, скопировал все ваши коды и вставил на одну страницу. Но получил ту же ошибку.
2. В вашем коде нет проблем. Вы правильно добавили поставщика: в файл pubspec.yaml. Какую версию провайдера вы используете? Конструкторы Const помогают Flutter перестраивать только виджеты, которые должны быть обновлены. Поскольку const являются константами времени компиляции, они повышают производительность вашего приложения, позволяя Flutter знать, что этот объект никогда не изменится в течение всего времени выполнения кода. Я пользователь dart lint dart-lang.github.io/linter/ lints это помечает код в IDE, где мне нужно ввести const .
3. Я проверил свой файл pubspec.yaml. Версия провайдера — «provider: ^ 4.3.2 2», поэтому последняя версия. Если вы хотите, я могу добавить файл pubspec.yaml в основной текст выше. Спасибо за объяснение константы.
4. Да, пожалуйста, добавьте свой pubspec.yaml к вашему основному вопросу.
5. Хорошо, я добавил файл pubspec.yaml