introduce
Dynamically switch topics using Provider status management
To learn the content of this chapter, you must master the state management of Provider. If you don’t understand, please open my home page, search for Provider, and then return to this blog
Theme Style Overview
factory ThemeData({
Brightness brightness, // Apply the overall theme brightness. Used for widgets such as buttons to determine what color to choose when you are not using a primary or accent color.
MaterialColor primarySwatch,// Define a single color and a block of ten shades.
Color primaryColor, // Background color for the main part of the application (toolbars, TAB bars, etc.)
Brightness primaryColorBrightness, // primaryColor brightness. ICONS used to determine the color of text and placed above the main color (for example, toolbar text).
Color primaryColorLight, // A lighter version of primaryColor
Color primaryColorDark, // The darker version of primaryColor
Color accentColor, // The foreground color of the widget (knob, text, overlay edge effect, etc.).
Brightness accentColorBrightness, // accentColor brightness.
Color canvasColor, // The default color of materialType.canvas
Color scaffoldBackgroundColor, // The default colour of Scaffold. The background color of a typical Material application or page within an application.
Color bottomAppBarColor, // The default color of BottomAppBar
Color cardColor, // The color of Card
Color dividerColor, // The colors of the Divider and PopupMenuDivider are also used between listtiles, between rows of the DataTable, etc.
Color highlightColor, // Select the highlight color to use during splash animation, or to indicate items in the menu.
Color splashColor, // The color of the ink splash. InkWell
InteractiveInkFeatureFactory splashFactory, // Define the appearance of the splash produced by the InkWell and InkResponse reactions.
Color selectedRowColor, // Use to highlight the color of the selected row.
Color unselectedWidgetColor, // The color used for widgets that are inactive (but enabled). For example, an unchecked check box. This is usually contrasted with accentColor. Also see disabledColor.
Color disabledColor, // Disable the color of the part in the state, regardless of its current state. For example, a disabled check box (which can be checked or unchecked).
Color buttonColor, // The default padding color for Material used in the RaisedButton.
ButtonThemeData buttonTheme, // Define the default configuration of button widgets, such as RaisedButton and FlatButton.
Color secondaryHeaderColor, // The color of the PaginatedDataTable title when the row is selected.
Color textSelectionColor, // The color of the text selected by the text box, such as TextField
Color cursorColor, // The color of the cursor in a text box, such as TextField
Color textSelectionHandleColor, // Adjusts the color of the handle to the currently selected text part.
Color backgroundColor, // A color that contrasts with the main color, e.g. used as the rest of a progress bar.
Color dialogBackgroundColor, // The background color of the Dialog element
Color indicatorColor, // The color of the selected TAB indicator in the TAB.
Color hintColor, // The color used to prompt text or placeholder text, as in TextField.
Color errorColor, // The color used for input validation errors, such as in TextField
Color toggleableActiveColor, // The color used to highlight the active state of swappable widgets like Switch, Radio, and Checkbox.
String fontFamily, // Text font
TextTheme textTheme, // The color of the text contrasts with the color of the card and canvas.
TextTheme primaryTextTheme, // Contrast the text theme with primaryColor
TextTheme accentTextTheme, // Contrast the text theme with accentColor.
InputDecorationTheme inputDecorationTheme, // Default InputDecorator, TextField, and TextFormField values based on this topic.
IconThemeData iconTheme, // An icon theme that contrasts the card and canvas colors
IconThemeData primaryIconTheme, // Contrast the icon theme with primaryColor
IconThemeData accentIconTheme, // An icon theme that contrasts with accentColor.
SliderThemeData sliderTheme, // Used to render the color and shape of the Slider
TabBarTheme tabBarTheme, // Theme for customizing the size, shape, and color of TAB bar indicators.
CardTheme cardTheme, // Card color and style
ChipThemeData chipTheme, // Chip's color and style
TargetPlatform platform,
MaterialTapTargetSize materialTapTargetSize, // Configures the hit test size for some Material components
PageTransitionsTheme pageTransitionsTheme,
AppBarTheme appBarTheme, // Theme for customizing Appbar colors, heights, brightness, iconTheme, and textTheme.
BottomAppBarTheme bottomAppBarTheme, // Customize the shape, height, and color of the BottomAppBar theme.
ColorScheme colorScheme, // There are 13 colors, which can be used to configure the colors of most components.
DialogTheme dialogTheme, // Customize the theme shape of the Dialog
Typography typography, // used to configure the color and geometry TextTheme values for TextTheme, primaryTextTheme, and accentTextTheme.
CupertinoThemeData cupertinoOverrideTheme
})
Copy the code
In actual combat
Introduction of package
Open pubspec.yaml of the Flutter project and directory because of the use of Provider state management and shared_preferences data persistence
Shared_preferences: ^ 0.5.12 + 4 provider: ^ 4.3.2 + 3Copy the code
Add a global theme color
To set the theme, we need to know how many themes (colors) our app needs. For this theme, we need to define a global list
Dart file to save the global theme color
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
final List<Color> themeList = [
Colors.blue,
Colors.black,
Colors.red,
Colors.purple,
Colors.indigo,
Colors.yellow,
Colors.green,
];
Copy the code
We’ll just define these colors, and if you want more, you can define them yourself
Add global topic state
Since our theme is dynamic, we need to notify the interface to refresh after changing. Here we need to use state management, if you are not familiar with Provider state management, please learn first and then watch
Create a provider folder in the project and directory lib. Create a theme_provider.dart file in the folder to save the current theme status value
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:zhong_mei_utils_flutter/global/Global.dart';
// Inherit ChangeNotifier
class ThemeProvider with ChangeNotifier {
Color _color = themeList.first;// The default is the first in the list of theme colors we set
void setTheme(int index) {// Provide external methods to modify the theme
print(index.toString());
_color = themeList[index];
notifyListeners();
}
Color get color => _color;// Get the current topic
}
Copy the code
The topic state class is created, added to the project, and let the project manage the state to modify main.dart
return runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
ChangeNotifierProvider(create: (context) => ThemeProvider()),
],
child: MyApp(),
));
Copy the code
With the topic state set, use the global topic state
Generally speaking, one app has only one MaterialApp, and our topic is set in the MaterialApp, so find our MaterialApp and add the following code
return MaterialApp(
theme: ThemeData.light().copyWith(
primaryColor: Provider.of<ThemeProvider>(context).color,
buttonTheme: ButtonThemeData(
buttonColor: Provider.of<ThemeProvider>(context).color,
textTheme: ButtonTextTheme.normal,
),
),
Copy the code
The previous code sets the app theme color and button color to use the color in the state manager, while the button text color is highlighted. If the button background color is black, the button text color is automatically white
Theme Modification interface
Add settings_theme.dart.dart under lib
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:weui/icon/index.dart';
import 'package:zhong_mei_utils_flutter/global/Global.dart';
import 'package:zhong_mei_utils_flutter/provider/ThemeProvider.dart';
class SettingsView extends StatefulWidget {
@override
_SettingsViewState createState() => _SettingsViewState();
}
class _SettingsViewState extends State<SettingsView> {
int _index;// Where in the global theme list is our current theme set?
@override
void initState() {
super.initState();
loadData();// Query current persistent data
}
void loadData() async {
SharedPreferences sp = await SharedPreferences.getInstance();// Get the persistent action object
setState(() {
_index = sp.getInt("theme")??0;// Query the theme field saved in the persistence framework. If it is null, it defaults to 0
});
}
Widget _itemBuilder(BuildContext context, int index) {
return GestureDetector(
child: Container(
width: double.infinity,
height: 50,
margin: EdgeInsets.only(top: 10, bottom: 10),
decoration: BoxDecoration(
color: themeList[index],
borderRadius: BorderRadius.all(Radius.circular(20)), ), child: _index ! = index ? Text("")// If not selected, there is nothing
: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
WeIcons.hook,// If it is selected, an icon is given. This icon is a check box, you can find it by yourself
color: Colors.white,
),
SizedBox(width: 16),
],
),
),
onTap: () async {
SharedPreferences sp = await SharedPreferences.getInstance();
sp.setInt("theme", index);// Click to modify the theme database in the persistence framework
Provider.of<ThemeProvider>(context, listen: false).setTheme(index);// Change the global status to the selected value
setState(() {
_index = index;// Set the current interface selection value, refresh the check box}); }); }@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Set theme"),
centerTitle: true,
elevation: 10,
),
body: Padding(
padding: EdgeInsets.all(20), child: Scrollbar( child: ListView.builder( itemBuilder: _itemBuilder, itemCount: themeList.length, ), ), ), ); }}Copy the code
At this point, we have finished, but there is a problem, that is, we have no problem with normal use, but after exiting the app, we did not read the persistent theme, so we changed the default first color
At this time we want to read data to see the theme, to understand a concept app starts, have white, developers can start to do a figure commonly, to cover up bad, we need to know here, hang because app on load some things, not rendering interface, so we load the theme should also be in the app before loading
Otherwise, the interface is rendered, but the theme is not read, causing the theme to display the default color first, and then display the theme color we set
So there is code in the Main. dart of the Flutter project
return runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
ChangeNotifierProvider(create: (context) => ThemeProvider()),
],
child: MyApp(),
));
Copy the code
As you can see, there is no UI rendering before Child: MyApp(), so we need to read the theme before return runApp and generate the ThemeProvider object
int theme;// Add a variable to receive a database read return
void main() async {// Async is added since reading from the database requires async
await loadData();// Read the topic saved by the database
ThemeProvider themeProvider = ThemeProvider();// New a topic state object
themeProvider.setTheme(theme ?? 0);// Set the object to the subject we read
return runFxApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
ChangeNotifierProvider(create: (context) => themeProvider),ThemeProvider() is the ThemeProvider object
],
child: MyApp(),
),
// onEnsureInitialized: (info) {},
enableLog: false,
uiBlueprints: uiSize,
);
}
void loadData() async {
SharedPreferences sp = await SharedPreferences.getInstance();
theme = sp.getInt("theme")??0;// Return 0 if read is null
}
Copy the code
After the above changes, we finished reading the persistent theme and preloaded the theme at app startup
Implementation effect demonstration
As you can see, the theme is up to date by the time you start the project and get to the landing page. Here we use persistence