Getting started: Build the Flutter development environment on macOS
Get the Flutter SDK
Go to the Flutter website to download its latest available installation package, Flutter SDK Releases, or go to the Github repository of Flutter to download Flutter/Flutter.
Update environment variables
Add tools for flutter to path:
export PATH=`pwd`/flutter/bin:$PATH
Copy the code
This code can only temporarily set the PATH environment variable to the current command line window. Adding Flutter to PATH permanently requires updating the environment variable so that you can run Flutter commands in any terminal session.
- Open (or create)
.bash_profile
, this file may have different file paths on different machines, for example on my computer in this path:/Users/hmc/.bash_profile
. if.bash_profile
If the file doesn’t existcd
到Users/ XXX (your current username)
Path, then usevim .bash_profile
The command creates one itself. - to
.bash_profile
Add the following line to the file and change itPATH_TO_FLUTTER_GIT_DIRECTORY
To download the Flutter SDK to the local path, for example my local path to the Flutter SDK is:/Users/hmc/Documents/GitHub/flutter
, line 3 in the following example is changed to:export PATH=/Users/hmc/Documents/GitHub/flutter/bin:$PATH
.
export PUB_HOSTED_URL=https://pub. Flutter - IO. Cn // Required for domestic users
export FLUTTER_STORAGE_BASE_URL=https:// Storage. Flutter - IO. Cn // This is required for domestic users
export PATH=PATH_TO_FLUTTER_GIT_DIRECTORY/flutter/bin:$PATH
Copy the code
- Open a terminal window to execute
source /Users/hmc/.bash_profile
Command to refresh (.bash_profile
The actual file path is subject to your own machine). - If the terminal uses ZSH, the terminal starts
~/.bash_profile
The file will not be loaded and the solution is to modify it~/.zshrc
The path of my machine is:/Users/hmc/.zshrc
), to which add:source ~/.bash_profile
. if.zshrc
If the file does not exist, run the following command to create it:
touch .zshrc
open -e .zshrc
Copy the code
Then enter source ~/.bash_profile and save it. Then enter source. ZSHRC to refresh the environment for the environment variables to take effect.
Run the Flutter Doctor
Run the flutter doctor command to see if additional dependencies need to be installed and complete the overall installation of the flutter environment. The Flutter doctor command checks your environment and displays a report in the terminal window. The Dart SDK is already bundled into the flutter and there is no need to install Dart separately. Scrutinize the command line output for additional software that may need to be installed or further tasks that may need to be performed (shown in bold).
If you already have an iOS development environment, the configuration of the Flutter environment is almost complete. With the above configuration, I run the Flutter doctor command on my machine (this command will be slow for the first time). The output is as follows:
hmc@localhost ~ % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, 2.5. 07.0.pre185., on macOS 11.4 20F5046g darwin-x64, Go onto those who qualify. Locale zh-Hans-cn) [Qualify] Android toolchain - Develop for Android devices eligible Android SDK. Install Android Studio from: https://developer.android.com/studio/index.html On first launch it will assist you in installing the Android SDK components. (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions). If the Android SDK has been installed to a custom location, Please use 'flutter config --android-sdk' to update to that location. [✓] Xcode - develop for iOS and macOS (Xcode)12.4Chrome - develop for the web [!] ✓ ✓ Android Studio (not installed) [✓] VS Code (version)1.421.[✓] Connected device ()2 available)
! Doctor found issues in 2 categories.
hmc@localhost ~ %
Copy the code
We see that the Android environment still needs to be configured, and we will do it later if necessary. The iOS environment for Flutter is now ready.
Get started: Configure the editor
Install Visual Studio Code
For the IDE part, we directly select Visual Studio Code version 1.20.1 or higher. Currently VS Code version has reached 1.59. After downloading and installing VS Code, we need to install the Flutter plug-in.
Install the Flutter plugin
Start VS Code, shift + Command + P bring up VS Code’s Command panel, type Install, then select Extensions: Install Extensions. Enter “flutter” in the search box and select “flutter support and debugger for Visual Studio Code” in the search list. Then click the Install button. When the installation is complete, select OK to restart VS Code.
3. Verify Settings with Flutter Doctor
Shift + Command + p bring up VS Code’s Command panel, type doctor, then select: Flutter: Run Flutter Doctor, which takes a moment to execute and then looks for the output, This will list details about your machine’s current Flutter version, local path, source, engine version, Dart version, Xcode version and location, CocoaPods version, Chrome location, VS Code version and location, plugin version, connected device, and more. My machine is as follows (android environment is not installed)
Flutter doctor -v [✓]Flutter (Channel master, 2.5. 07.0.pre185., on macOS 11.4 20F5046g darwin-x64, locale zh-Hans-CN)
• Flutter version 2.5. 07.0.pre185.The at/Users/HMC/Documents/lot/flutter, Upstream repository HTTPS://github.com/flutter/flutter.git
• Framework revision 2526cb07cb (2 days ago), 2021- 08- 21 23:42:01 - 0400.
• Engine revision 4783663Ee4, Dart version2.15. 0 (build 2.15. 041.0.dev)
• Pub download mirror https://pub.flutter-io.cn
• Flutter download mirror https://storage.flutter-io.cn[University] Android Toolchain-developforAndroid Devices Qualify Unable to locate Android SDK. Install Android Studio from: HTTPS://developer.android.com/studio/index.html
On first launch it will assist you in installing the Android SDK components.
(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).If the Android SDK has been installed to a custom location, Please use 'flutter config --android-sdk' to update to that location. [✓] xcode-developfor iOS and macOS (Xcode 12.4), Xcode ats/Applications/Xcode. The app/Contents/Developer, CocoaPods version1.101.✓ Chrome - developforThe web, Chrome at/Applications/Google Chrome app/Contents/MacOS/Google Chrome [!] AndroidStudio (notInstalled), the Android Studionot found; download from https://developer.android.com/studio/index.html
(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).✓ VSCode (version 1.421.), VS Code at/Users/HMC/Downloads/Visual Studio Code- 2.App /Contents • Flutter Extension version3.81.✓ Connecteddevice (3The available), the iPhone12• FF9BFB96 (mobile)-8FF44 -AD6-98B8- 1C8889653AF0, ios, com. Apple. CoreSimulator. SimRuntime. Ios- 144 -(simulator), the iPhone12 Pro• CC2922E4 - A2DB (mobile)43 -DF-8B6 f - D2987F683525, ios, com. Apple. CoreSimulator. SimRuntime. Ios- 144 -(simulator)Chrome• Chrome • Web -javascript • Google Chrome92.04515.159.
! Doctor found issues in 2 categories.
exit code 0
Copy the code
The IDE configuration is now complete.
Get started: Simple experience
This section creates a new Flutter application from our template, runs it, and learns how to update the Reload using Hot Reload.
Create a new application for Flutter
Shift + Command + p bring up VS Code’s Command panel, enter flutter, and select flutter: New Project, and then enter the Project name in the input field (e.g. When the project is created, VS Code will select and open the main.dart file by default. Make sure that the target device is selected in the lower right corner of VS Code. Then press F5 or call Debug > Start Debugging to wait for the application to Start. If everything is normal, after the application is created and started successfully, you should see the screenshot of the application on the device or emulator as follows:
Two, thermal overload
Flutter can have a fast development cycle through hot reload, which means that the modified code can be loaded in real time without any loss of state without restarting the application (developed natively, any change to a line of code must be recompiled to take effect). Simply make a change to the code, then tell the IDE or command-line tool that you need to Reload (hit the Hot Reload button) and you’ll see the change on your device or emulator. If You have pushed the button this many times: string content in the main.dart file and click Command + S to save, You can immediately see the updated string on the simulator.
Officially write the first Flutter App
Create a new Flutter project named Startup_namer. Dart simply delete all the code in lib/main.dart and run it with the following code, which simply displays a blue navigation bar with the title Welcome to Flutter and Hello World text in the center of the screen.
/ / incoming material. The dart
import 'package:flutter/material.dart';
// the => symbol is shorthand for a single-line Dart function/method, like void main() {runApp(new MyApp()); }
// The runApp function takes an instance of MyApp
void main(a) = >runApp(new MyApp());
// The MyApp class inherits from StatelessWidget
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Welcome to Flutter'.// Scaffold comes from the Material library
home: new Scaffold(
/ / the navigation bar
appBar: new AppBar(
// Navigation bar title
title: new Text('Welcome to Flutter'),),// Home screen contents
body: new Center(
/ / text widget
child: new Text('Hello World'),),),); }}Copy the code
The above example creates a Material APP. Material is a standard visual design language for mobile and Web. Flutter provides a rich set of Material Widgets.
The MyApp class inherits from StatelessWidget, which makes the application itself a widget. Most things in Flutter are widgets, including alignment, padding, and layout.
The Scaffold is a widget provided in the Material Library that provides the default navigation bar, title, and body property containing the widget tree on the main screen. Widget trees can be complex. The main job of a widget is to provide a build() method that describes how to display itself against other lower-level widgets.
The body widget tree in the example contains a Center widget, which in turn contains a Text widget as a child widget. The Center Widget aligns its child widget tree to the Center of the screen.
Using external packages
In the above example, we used the default package of flutter/material. Dart. Now we try to import other custom packages. (This section uses the introduction of the English_words 4.0.0 package, a utility for processing English words. Count syllables, generate word combinations that sound good, and provide the top 5,000 English words by usage.)
At pub.dartlang.org we can see the package with many different functions, we searched in it: english_words 4.0.0.
Modify the pubspec.yaml file to specify the package to be imported
The pubspec.yaml file is used to manage assets (such as images, packages, etc.) of the Flutter application. Yaml file, add english_words: ^4.0.0 to dependencies: as a dependency of the current program. The complete contents of the current pubspec.yaml file for the Flutter application startup_namer are as follows:
name: startup_namer
description: A newThe following line prevents the package from being accidentally published to pub.dev using 'Flutter pub publish'. This is aprivatePreference for Packages. publish_to:'none'# If you wish to publish to pub.dev, delete the line # below which the version number and build number of the application are defined. The version number is a three-digit dot separated number, such as1.243., followed by the optional build number separated by a +. Both the build and builder numbers can be overwritten by a FLUTTER build by specifying --build-name and --build-number respectively. # # In Android, build-name is used as the versionName and build-number as the versionCode. # Read more about Android versioning at https://developer.android.com/studio/publish/versioning# # in iOS, build - the name used for CFBundleShortVersionString, and build - number used 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.12.0 < 3.0.0"
# dependencies Specifies other packages that your package needs to work. To automatically upgrade your package Dependencies to the latest version, consider running the flutter pub upgrade -- majority-versions directive.Alternatively, you can manually update the Dependencies by changing the following version number to the latest version provided on pub.dev. To see which dependencies have more recent versions available, run the flutter pub outdated directive. Add the Cupertino Icons font to your application below. Used with the CupertinoIcons class for iOS style ICONS. cupertino_icons: ^1.02.# introduce english_words english_words: ^4.0. 0Dev_dependencies: flutter_test: SDK: flutter #"flutter_lints"The package includes a set of recommended LinTs to encourage good coding practices.Lint sets provided by # package are located in package root"analysis_options.yaml"File active.# See this file for information about disabling specific Lint rules and enabling other rules. flutter_lints: ^1.0. 0For information about the common Dart section of this file, see the following page: HTTPS://dart.dev/tools/pub/pubspec# The following sections are specific to Flutter. Flutter: # The following line makes sure to include the Material Icons font in your application so that you can use Icons in the Material Icons class. uses-material-design:trueTo add assets (usually images) to your app, add the Assets section as follows:# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# Image Asset can reference one or more resolution-specific"variants"(variant), see HTTPS://flutter.dev/assets-and-images/#resolution-aware.For details about adding assets to package Dependencies, see HTTPS://flutter.dev/assets-and-images/#from-packages To add a custom font to your application, add this here"flutter"Part of the font part. Each entry in this list should have one with the font family"family"Key, and one with a list"fonts"Key, which provides 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: 700Add package dependencies to package dependencies.//flutter.dev/custom-fonts/#from-packages
Copy the code
(I’ll leave it to the analysis_options.yaml file, which covers the introduction of package first.)
The introduction of english_words: ^4.0.0 in pubspec.yaml files provides many other features besides the ability to import dependencies.
^4.0.0 after english_words directly indicates the version of this package. If the upgrade number is not specified, you can use the flutter pub upgrade — majority-versions command to upgrade the dependent package to the latest version, or manually change the version number to a specified version, specifying the latest version to manually update the package. Run the flutter pub outdated directive to see which dependent packages have a more recent version available. We are currently up to date, so the print is not found.
hmc@bogon startup_namer % flutter pub outdated
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
hmc@bogon startup_namer %
Copy the code
Running the flutter pub upgrade –major-versions command will print the following. As you can see, cupertino_icons are now 1.0.3, but they have not been updated directly since we specified ^1.0.2 directly in pubspec.yaml. Also flutter_lints latest is 1.0.4, and then specified in pubspec.yaml is ^1.0.0, which is also not forced to update.
hmc@bogon startup_namer % flutter pub upgrade --major-versions
Resolving dependencies...
async 2.82.
boolean_selector 2.1. 0
characters 1.1. 0
charcode 1.31.
clock 1.1. 0
collection 1.15. 0
cupertino_icons 1.03.
english_words 4.0. 0
fake_async 1.2. 0
flutter 0.0. 0 from sdk flutter
flutter_lints 1.04.
flutter_test 0.0. 0 from sdk flutter
lints 1.01.
matcher 0.1211.
meta 1.7. 0
path 1.8. 0
sky_engine 0.099. from sdk flutter
source_span 1.81.
stack_trace 1.10. 0
stream_channel 2.1. 0
string_scanner 1.1. 0
term_glyph 1.2. 0
test_api 0.43.
typed_data 1.3. 0
vector_math 2.1. 0
No dependencies changed.
No changes to pubspec.yaml!
hmc@bogon startup_namer %
Copy the code
The pubspec.yaml file also specifies the version number and build number, as well as introducing image resources and font resources.
2. Get package
Run the flutter packages get/flutter pub get to pull the package introduced in the pubspec.yaml file. They will be downloaded to /Users/ HMC /.pub-cache/ Hosted /pub. Flutter – IO. Cn. You can see the following output:
hmc@bogon startup_namer % flutter packages get
Running "flutter pub get" in startup_namer... 565ms
hmc@bogon startup_namer % flutter pub get
Running "flutter pub get" in startup_namer... 579ms
hmc@bogon startup_namer %
Copy the code
3. Introduce package into your code
At the top of the lib/main.dart file we can introduce the package to use as follows:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
Copy the code
There is also a dot where we imported english_words/english_words.dart and they are grayed out when our code below is not using them, which indicates that the library we imported is not used (yet).
4. Use the imported package
Let’s replace Hello World with a string of English words generated by the function in the English_words package.
Tip: Camel nomenclature (called “upper Camel case” or “Pascal case”), which means that every word in the string (including the first word) begins with a capital letter. So, “upperCamelCase” becomes “upperCamelcase”.
The code is modified as follows:
import 'package:flutter/material.dart';
// ⬇️ imports content from english_words
import 'package:english_words/english_words.dart';
void main(a) { runApp(new MyApp()); }
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ⬇️ calls the random function of the WordPair class to generate a random WordPair
final wordPair = new WordPair.random(a);return new MaterialApp(
title: 'Welcome to Flutter',
home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),
),
body: new Center(
// ⬇️ comments "Hello World", then wordPair is converted to camel name and displayed in the center of the screen
// child: new Text('Hello World'),
child: new Text(wordPair.asPascalCase), ), ), ); }}Copy the code
5, hot overload test package use
If the application is running, click the Hot Reload button (⚡️ Lightning icon: Hot Reload) to update the running application. Each time you hit hot reload or save the project, a different word pair is randomly selected in the running application, and you can see the different word pairs displayed in the center of the emulator. This is because the wordPair variable is generated within the Build method. The Build function is run (re-run) every time the MaterialApp needs to render or switch platforms in the Flutter Inspector. Final wordPair = new wordPair. Random (); The new wordPair variable is generated. (Final wordPair = new wordPair. Random (); The words in the center of the emulator screen do not change.
Adding a Stateful Widget
Class MyApp extends StatelessWidget {ejbateful widget} class MyApp extends StatelessWidget {ejbateful widget} class MyApp extends StatelessWidget {ejbateful widget} }, see that MyApp inherits from StatelessWidget, and we’ll focus on the StatefulWidget class in this section.
Stateless widgets are immutable, which means their properties cannot be changed and all values are final. State owned by Stateful Widgets can change during the widget life cycle.
Implementing a Stateful Widget requires at least two classes:
- a
StatefulWidget
Class. - a
State
Class.StatefulWidget
The class itself is constant, butState
Classes exist throughout the widget life cycle.
In this section we will add a subclass of the StatefulWidget class called RandomWords, override the createState function of the RandomWords class, and return an instance object of a subclass of State called RandomWordsState. The State class will eventually maintain suggested and preferred word pairs for the widget. (An array of wordpairs holds suggested word pairs, and a collection of wordpairs holds favored word pairs.)
Let’s begin this section.
- Add stateful
RandomWords widget
Go to the bottom of the main.dart file. It can be used anywhere outside of the MyApp file, but this example puts it at the bottom of the main.dart file. inRandomWords widget
The interior just rewrites itscreateState
Function, createState
Class, the others didn’t do anything. So let’s analyze itcreateState
Function.
class RandomWords extends StatefulWidget {
@override
createState(a) = >new RandomWordsState(a); }Copy the code
The State
createState() function is used to create a variable State at a given location in the widget tree (the function returns a value of State
). StatefulWidget subclasses should override this method and return a newly created instance of their associated State subclass.
@override
State<MyWidget> createState(a) => _MyWidgetState();
Copy the code
The framework can call this method multiple times during the life of a StatefulWidget. For example, if a widget is inserted into the Widget tree at multiple locations, the framework creates a separate State object for each location. Similarly, if the widget is removed from the tree and later inserted back into the tree, the framework calls the createState function again to create a new State object, simplifying the life cycle of the State object.
- add
RandomWordsState
Class. Most of the application’s code is in this class, which holdsRandomWords widget
In the state. This class will save the generated random word pairs that grow infinitely as the user scrolls, as well as the selected word pairs that the user clicks repeatedly on the heart-shaped ❤️ icon to add or remove word pairs from the list. First of all defineRandomWordsState
Class, to which we will add content step by step.
class RandomWordsState extends State<RandomWords> {
// ...
}
Copy the code
- The statement
RandomWordsState
Class, the IDE will prompt usRandomWordsState
Such a lack ofbuild
Method, let’s rewritebuild
Method and put before inMyApp
Code to generate random word pairs inRandomWordsState
To generate word pairs. Example code is as follows:
class RandomWordsState extends State<RandomWords> {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random(a);return new Text(wordPair.asPascalCase); }}Copy the code
- The following example code, modify the old code before the generation of random word pairs from the code
MyApp
Move to theRandomWordsState
In the.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ⬇️ comment out this line to create the wordPair local variable
// final wordPair = new WordPair.random();
return new MaterialApp(
title: 'Welcome to Flutter',
home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),
),
body: new Center(
// child: new Text('Hello World'),
// ⬇️ comment this line, using the RandomWords instance object below, to return a random word pair
// child: new Text(wordPair.asPascalCase),
child: new RandomWords(),),),); }}Copy the code
Restart the application, and the application will remain the same. Each time you hot-reload or command + S saves the application, a new pair of words will appear in the center of the screen.
Here is the complete code for the above example:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main(a) { runApp(new MyApp()); }
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
return new MaterialApp(
title: 'Welcome to Flutter',
home: new Scaffold(
appBar: new AppBar(
title: new Text('Welcome to Flutter'),
),
body: new Center(
// child: new Text('Hello World'),
// child: new Text(wordPair.asPascalCase),
child: new RandomWords(),),),); }}class RandomWords extends StatefulWidget {
@override
createState(a) = >new RandomWordsState(a); }class RandomWordsState extends State<RandomWords> {
@override
Widget build(BuildContext context) {
final wordPair = new WordPair.random(a);return new Text(wordPair.asPascalCase); }}Copy the code
Create an infinite scrolling ListView
In the last section, inside the RandomWordsState class we simply overwrote its build function to return a random pair of words. In this section, we continue to extend the RandomWordsState class to generate and display a list of word pairs. As we swipe up, the ListView grows infinitely to show randomly generated pairs of words.
ListView’s builder factory constructor allows us to create a lazy-loaded ListView on demand (return new listview.builder (…)). 😉 .
- We created it first in the previous section
RandomWordsState
Class to add onefinal _suggestions = <WordPair>[];
Array is used to hold the suggested word pairs. The variable name starts with an underscore, which in the Dart language prefixes the identifier to force it to be private. Add another one_biggerFont
Variable to increase the font size.
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); . }Copy the code
- to
RandomWordsState
Class to add one_buildSuggestions()
Function that is used to build a display of suggested word pairsListView
.ListView
Class provides onebuilder
Properties,itemBuilder
Value is an anonymous callback function that takes two argumentsBuildContext, int
.(context, i)
.i
Row iterator, iterator starts at 0, and every time this function is called,i
Is incremented by 1, executed once for each suggested word pair, and the model allows the list of suggested word pairs to grow indefinitely as the user scrolls.
class RandomWordsState extends State<RandomWords> {
...
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
// The itemBuilder is called once for each suggested word pair, and the word pair is added to the ListTile row,
// On even lines, this function adds a ListTile row to the word pair,
// On odd lines, the function adds a divider widget to separate adjacent pairs of words.
// Note that on a small screen, the splitter line can look a bit labored.
// (in iOS TableView, the partition line is on a Cell, and the partition line and each word pair are on a Cell)
itemBuilder: (context, i) {
// before each column, add a 1 pixel high divider widget (starting from 0, isOdd determines whether it isOdd)
if (i.isOdd) return new Divider(a);// the syntax 'I ~/ 2' represents the quotient (rounded down) of I divided by 2, and returns an integer (rounded down), such as: 1,2,3,4,5. The result is: 0,1,1,2,2,
// From this we can calculate the actual number of word pairs in the ListView after subtracting the separator lines.
final index = i ~/ 2;
// If it is the last word pair in the suggested word list, expand the capacity.
if (index >= _suggestions.length) {
// Then regenerate 10 word pairs and add them to _suggestions.
_suggestions.addAll(generateWordPairs().take(10));
}
// _buildRow parses below.
return_buildRow(_suggestions[index]); }); }... }Copy the code
- For each word pair,
_buildSuggestions
All functions are called once_buildRow
Function. This function is inListTile
Display each new word pair in, which can enable us toListView
Generate each display row inRandomWordsState
Class to add_buildRow
Function.
class RandomWordsState extends State<RandomWords> {
...
Widget _buildRow(WordPair pair) {
return new ListTile(
title: new Text(
// For each line of displayed text, word pairs are changed to hump naming
pair.asPascalCase,
// The size is 18 (' final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); `)style: _biggerFont, ), ); }}Copy the code
- So let’s update
RandomWordsState
Of the classbuild
Function to use what we wrote above_buildSuggestions()
Function, instead of directly generating just one word pair.
class RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
// return new Text(wordPair.asPascalCase);
// return Sacffold to take over the contents of MyApp.
return new Scaffold(
/ / the navigation bar
appBar: new AppBar(
/ / title
title: new Text('Startup Name Generator'),),// Body calls _buildSuggestions() to build a ListViewbody: _buildSuggestions(), ); }}Copy the code
- update
MyApp
In the classbuild
The contents of the function. fromMyApp
Remove theScaffold
和AppBar
Instance. These will be made byRandomWordsState
Class, which makes it easier to change the route name (navigation bar title) in the navigation bar as you navigate from one screen to another in the next step.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
return new MaterialApp(
// title: 'Welcome to Flutter',
// home: new Scaffold(
// appBar: new AppBar(
// title: new Text('Welcome to Flutter'),
/ /),
// body: new Center(
// // child: new Text('Hello World'),
// // child: new Text(wordPair.asPascalCase),
// child: new RandomWords(),
/ /),
// ),
title: 'Startup Name Generator',
home: new RandomWords()); }}Copy the code
Restart the application, and we’ll see a list of word pairs, scroll down as far as we can, and we can scroll down as far as we can, and we’ll always see new word pairs generated.
Add the interaction
In this step, we will add a clickable heart-shaped ❤️ icon to each row of the ListView. When we click on an item in the ListView, we toggle the item’s “favorites” status, adding or removing the word pair from “favorites.”
- Add a
final _saved = new Set<WordPair>();
Set toRandomWordsState
Class, this collection is used to store pairs of words that the user clicked to like. useSet
比List
A more appropriate,Set
The uniqueness of the elements is guaranteed.
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = new Set<WordPair>();
final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); . }Copy the code
- in
_buildRow()
Methodfinal alreadySaved = _saved.contains(pair);
To check to make sure word pairs have not been added to favorites.
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair); . }Copy the code
- At the same time
_buildRow()
In, add a heart-shaped ❤️ icon toListView
To enable favorites. Now you can add interactive capabilities to the heart-shaped ❤️ icon.
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
// Add a heart icon
trailing: new Icon(
// And depending on whether the current word pair is already bookmarked, the heart icon is displayed differently (hollow indicates unbookmarked, solid red indicates bookmarked).
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
);
}
Copy the code
-
Restart the app and you can see a hollow heart icon to the right of each pair of words in a row, without any interaction events.
-
Making the heart icon change in _buildRow can be clicked (note that the interaction event is added to each row of the ListView). If the word pair has been added to the favorites, click again to remove it from the favorites. The function call setState() notifies the frame that the state has changed when each pair of words in the line is clicked.
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
// Add a heart icon
trailing: new Icon(
// And depending on whether the current word pair is already bookmarked, the heart icon is displayed differently (hollow indicates unbookmarked, solid red indicates bookmarked).
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
// Add interactive events to each row of the ListView
onTap: () {
setState(() {
// Click the event to remove the current word pair from the _saved set if it is already saved, otherwise add it to the _saved set
if (alreadySaved) {
/ / remove
_saved.remove(pair);
} else {
/ / add
_saved.add(pair); }}); }); }Copy the code
Note: In the reactive style framework of Flutter, calling the setState() function triggers the build method for the State object, which causes an update to the UI.
Navigate to a new page
In this section, we will add a page that displays favorites (called routes in Flutter) and learn how to navigate between the primary route and the new route (switching pages).
In Flutter, the navigator manages the application’s routing stack. Pushing a route into the navigator’s stack will display a page updated to that route. Popping a route from the navigator’s stack displays a return to the previous route.
- in
RandomWordsState
Of the classbuild
Method forAppBar
Add a list icon so that when the user clicks on the list icon, the new routing page with favorites is displayed on the stack.
Note: Some widget properties require a single widget (child), while others, if action, require a set of widgets (children), represented by square brackets [].
Add the icon and its corresponding action to the Build method:
class RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
// final wordPair = new WordPair.random();
// return new Text(wordPair.asPascalCase);
return new Scaffold(
appBar: new AppBar(
title: new Text('Startup Name Generator'),
// Actions is a set of interactions, we just need an interaction icon to jump to a favorites route
actions: <Widget>[
// Favorites button. When clicked, _pushSaved is called. Its Icons are styled icons.list
new IconButton(onPressed: _pushSaved, icon: new Icon(Icons.list)), ], ), body: _buildSuggestions(), ); }... }Copy the code
- to
RandomWordsState
Class to add_pushSaved()
Function.
class RandomWordsState extends State<RandomWords> {
...
void _pushSaved() {
// ...}}Copy the code
Hot reloading the application shows a button-like list icon on the right of the navigation bar. Clicking on it doesn’t do anything yet, because _pushSaved() hasn’t added anything yet.
- When the user clicks the list icon on the right of the navigation bar, a route is created and pushed into the navigation manager’s stack, which switches the page to show the new route. The content of the new page is in
MaterialPageRoute
的builder
Property,builder
Is an anonymous function. addNavigator.push
Call, which pushes the route to the navigation manager’s stack.
void _pushSaved() {
Navigator.of(context).push(
);
}
Copy the code
- add
MaterialPageRoute
And itsbuilder
. Now, add the buildListTile
Line of code.ListTile
的divideTiles()
Method in everyListTile
Add a 1 pixel line between them. thedivided
The variable holds the final list item.
void _pushSaved() {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
// Iterate over each word pair collected in _saved
final tiles = _saved.map(
(pair) {
// Build a ListTile row for each word pair
return new ListTile(
title: new Text( pair.asPascalCase, style: _biggerFont, ), ); });// Add a 1 pixel divider between each ListTile
final divided = ListTile.divideTiles(
context: context,
// Build above
tiles: tiles,
).toList(a); },),); }Copy the code
builder
Returns aScaffold
, which contains the nameSaved Suggestions
Navigation bar for the new route. The new road by thebody
By containingListTiles
theListView
Each line is separated by a dividing line.
void _pushSaved() {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
// Iterate over each word pair collected in _saved
final tiles = _saved.map(
(pair) {
// Build a ListTile row for each word pair
return new ListTile(
title: new Text( pair.asPascalCase, style: _biggerFont, ), ); });// Add a 1 pixel divider between each ListTile
final divided = ListTile.divideTiles(
context: context,
// Build above
tiles: tiles,
).toList(a);// New routing page
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Suggestions'),),// ListView
body: new ListView(children: divided), ); },),); }Copy the code
- Hot-reload the application, bookmark some word pairs, and click the list icon on the navigation bar to display the bookmarked contents on the new routing page. Note that the navigator adds a “back” button to the navigation bar, which we don’t have to implement explicitly
Navigator.pop
Click the back button to return to the home route.
conclusion
So far we have learned to do a simple Flutter of scrollable, interactive, routing applications, at the same time we should also have a to Flutter in the, it compared with native development efficiency is high, the thermal overload also too love, native at the one line of code to recompile operation are “hip”! So that’s it for this article, and then we’ll start to learn more about Flutter! ⛽ ️ ⛽ ️ 🎉 🎉 🎉
Refer to the link
Reference link :🔗
- Mac Pro cannot find ZSHRC file
- Write your first Flutter App