В настоящее время функция темного режима стала для всех стандартной настройкой дисплея по многим причинам, таким как способность продлить время работы устройства от батареи, уменьшить напряжение глаз и улучшить видимость для людей с низким зрением, чувствительных к яркому свету.
Поэтому важно, чтобы приложения предоставляли пользователям возможность выбора темы дисплея. В этой статье мы рассмотрим самый простой способ добавить функцию темного режима в приложение flutter.
Необходимые условия
-
Базовые знания о dart
-
Базовые знания о flutter
-
Мы будем использовать два полезных встроенных класса flutter: ValueNotifier и valueListenableBuilder.
valueNotifier:
valueNotifier — это changeNotifier, который содержит только одно значение, уведомляющее виджет, который слушает, когда начальное значение было изменено. Это значение может быть любого типа, что помогает улучшить производительность приложения, перестраивая только тот виджет, к которому необходимо применить изменение.
valueListenableBuilder:
valueListenableBuilder, как следует из названия, является виджетом, который всегда прикреплен к valueListenable и проверяет, изменилось ли значение valueNotifier, а затем создает новый виджет соответственно. Подумайте о функции, которая используется в вашем приложении, и вы бы хотели, чтобы ваше приложение обновлялось всякий раз, когда или где бы эта функция ни изменилась.
Реализация функции темного режима
Давайте приступим к реализации функции темного режима. Мы создадим новое приложение flutter, название приложения можно выбрать по своему усмотрению, но для целей этой статьи мы назовем наше приложение dark_theme.
Файл main.dart
Файл main.dart — это место, где будет создано наше материальное приложение, и в материальном приложении мы выделим некоторые из этих свойств: ValueNotifier, ValueListenableBuilder, ThemeMode, DarkTheme.
Вот как будет выглядеть код для main.dart:
import 'package:flutter/material.dart';
import 'firstscreen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
// Using "static" so that we can easily access it later
static final ValueNotifier<ThemeMode> themeNotifier = ValueNotifier(ThemeMode.light);
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<ThemeMode>(valueListenable: themeNotifier,
builder: (_, ThemeMode currentMode, __) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Dark Mode',
theme: ThemeData(primarySwatch: Colors.purple),
darkTheme: ThemeData.dark(),
themeMode: currentMode,
home: const FirstScreen(),
);
});
} //MaterialApp
} //ValueListenerBuilder
В приведенном выше фрагменте кода :
ValueNotifier имеет свойство ThemeMode с именем переменной ThemeNotifier, которое установлено в светлый режим по умолчанию.
ValueListenerBuilder также имеет свойство ThemeMode с ValueNotifier, который слушает ThemeNotifier, чтобы проверить, изменилось ли значение ThemeNotifier, и затем уведомляет конструктор, если значение изменилось, чтобы перестроить виджет.
ThemeMode будет определять режим приложения, если доступны Theme (который включает ThemeMode.system и ThemeMode.light) и darkTheme.
Я добавил небольшой твик в наши ThemeData, чтобы изменить внешний вид с нашего обычного синего цвета на фиолетовый. Вы также можете поиграть с цветами и найти тот, который подходит вашему режиму.
файл firstscreen.dart
Мы создадим еще один файл под названием firstscreen, чтобы показать, как кнопки реагируют на смену тем и цветов.
Вот как выглядит код для первого экрана:
import 'package:dark_theme/secondscreen.dart';
import 'package:flutter/material.dart';
import 'main.dart';
class FirstScreen extends StatelessWidget {
const FirstScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Theme app'),
actions: [
IconButton(
icon: Icon(MyApp.themeNotifier.value == ThemeMode.light
? Icons.dark_mode
: Icons.light_mode),
onPressed: () {
MyApp.themeNotifier.value =
MyApp.themeNotifier.value == ThemeMode.light
? ThemeMode.dark
: ThemeMode.light;
})
],
),
body: Center(
child: SizedBox(
width: 300,
height: 100,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15))
),
child: const Text('Go to second Screen',
style: TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const SecondScreen()));
},
),
),
),
);
}
}
Во всех приведенных выше фрагментах кода мы будем рассматривать материальный виджет iconButton, в котором находятся наши иконки и оператор троичности.
Теперь в виджете iconButton у нас будет тернарная операция, которая включает в себя две иконки, одну для темной темы (darkTheme) и одну для светлой (lightTheme), которые будут icons.dark_mode и icons.light_mode соответственно, и в тернарной операции мы скажем, что если значение themeNotifier установлено в thememode.light, то иконка icons.light_mode должна быть отображена в пользовательском интерфейсе приложения, в противном случае отображается иконка icons.dark_mode.
Теперь после этого переходим к свойству onPressed, где у нас есть еще одна десятичная операция, которая просто говорит, что при нажатии кнопки iconsButton, если значение themeNotifier равно themeMode.light, тема изменяется на themeMode.dark, в противном случае тема изменяется на ThemeMode.light.
ВЫХОД
файл secondscreen.dart
Давайте создадим еще один файл под названием Secondscreen, чтобы показать, как текст будет реагировать на изменения и лучше увидеть макет пользовательского интерфейса.
Вот код для второго экрана:
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
const SecondScreen ({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('second Screen'),
),
body: const Center(
child: Text(
'Hello',
style: TextStyle(fontSize: 50),
),
),
);
}
}
ВЫХОД
Заключение
поздравляем, мы добрались до конца статьи, и сделаем небольшой обзор того, что мы обсудили, мы узнали о value notifier и как он хранит одно значение, мы поговорили о виджете ValueLIstenableBuilder и как он проверяет, изменилось ли значение в valueNotifier и перестраивает конкретный виджет, прикрепленный к нему. Мы также увидели, как использовать valueNotifier и valueLIstenableBuilder в этом приложении, и что мы можем настроить наши themeData под различные приложения, если заданные, например lightTheme, нам не подходят. Используя iconButton, мы смогли соответствующим образом изменить иконки и установить, что происходит при нажатии на iconButton, используя тернарную операцию.
Пожалуйста, оставьте комментарий и поделитесь этой статьей, чтобы помочь другим понять, как использовать эту функцию в своем проекте, спасибо.