IDE: Android Studio
Major Project documents
First we create a Flutter project with a lowercase, underlined link, such as “first_project”, not “firstProject” or “firstProject”. After creating the project, see the following figure. Dart and pubspec.yaml are the two main files we will use today. Dart is the file in which the main method resides, the entry to the project, and pubspec.yaml is a reference to third-party Packages dependencies.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
title: "demo app",
home: new Scaffold(
appBar: new AppBar(
title: new Text("Welcome to flutter"),
),
body: new Center(
child: new Text("Hello World"),),),); }}Copy the code
The interface runs as follows:
Reference external Package
Here’s an example of an open-source software package called English_Words, which contains thousands of commonly used English words and features. There are many useful open source toolkits available at pub.dartlang.org. The pubspec.yaml file manages the static resources of the Flutter application. Add an english_words dependency to the file as follows:
"> < span style =" font-size: 14px; line-height: 20pxCopy the code
Click the Packages Get in the upper right corner to pull the Packages into the project. The console output is complete as follows.
--no-color packages get
Running "flutter packages get" in first_project...
Process finished with exit code 0
Copy the code
Import the package into lib/main.dart.
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
Copy the code
Now we use the WordPair class in this package to generate random words instead of Hello World in code like this. The red line is the new code. Then click the Flutter Hot Reload button on the toolbar to Reload the page. Generating random words instead of Hello World.
Use stateful widgets
As you can see from the code above, the App inherits a StatelessWidget class that makes itself a widget. In Flutter, most of the time everything can be seen as a widget. The widget’s main method is to provide a build() method that describes how the widget is presented against other lower-level widgets. The above example includes a Text Child widget and a Center widget that aligns all of its subtrees to the Center of the screen. The Stateless widget cannot be changed, which means that its properties cannot be changed either, and all values are final. To implement a Stateful widget, at least two conditions are required: 1) a StatefulWidget class; 2) This class creates an instance of the State class. The StatefulWidget class itself is immutable, but the State class can exist throughout the widget life cycle. Dart creates a StatefulWidget class RandomWords that inherits StatefulWidget, creates a RandomWordsState class that inherits State, and instantiates the latter in the RandomWords class. RandomWordsState will save the state of RandomWords to implement a stateful widget. Here’s the code.
class RandomWords extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new RandomWordsState();
}
}
class RandomWordsState extends State<RandomWords>{
@override
Widget build(BuildContext context) {
// TODO: implement build
}
}
Copy the code
Let’s add the widget to our page and describe the content to display in the Build of RandomWordsState. Then display the widget inside the body with the same effect as this:
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
title: "demo app",
home: new Scaffold(
appBar: new AppBar(
title: new Text("Welcome to flutter"),
),
body: new Center(
child: new RandomWords()
),
),
);
}
}
class RandomWords extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new RandomWordsState();
}
}
class RandomWordsState extends State<RandomWords>{
final wordPair = new WordPair.random();
@override
Widget build(BuildContext context) {
// TODO: implement build
returnnew Text(wordPair.asPascalCase); }}Copy the code
Most of the action is done inside The RandomWordsState, where RandomWords doesn’t have to do much.
The use of the ListView
Lists are also common in page layouts, so here we extend the RandomWordsState class to generate and display a list of phrases. Let’s start by defining an array of recommended phrases and a font style.
final _suggestions = <WordPair>[];
final _fontSize = new TextStyle(fontSize: 16.0);
Copy the code
Create a _buildRow function and pass in WordPair to render the widget tree displayed on each line of the ListView.
Widget _buildRow(WordPair pair){
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _fontSize,
),
);
}
Copy the code
Create a _buildSuggestions() function to build the ListView. The ListView provides an itemBuilder property, which is a factory build, and is called back as an anonymous function. It takes two arguments, the context context and the line I iterator. Each recommendation in the array is called once. The iterator starts at 0 and incremented by 1 each time. In this example, I will add 20 suggestions to the array and then render them to the ListView. The _buildSuggestions code is shown below.
Widget _buildSuggestions(){
_suggestions.addAll(generateWordPairs().take(20));
return new ListView.builder(
itemBuilder: (context,i){
return_buildRow(_suggestions[i]); }); }Copy the code
When I run it, I see the list. However, I found a problem when I pulled up and swiped. After more than 20 items, I could scroll down, with a blank screen, as shown in the figure.
This happens because the Builder constructor of the ListView runs on demand to build delayed-loading views. Just judge the iterator and do not render the view beyond the length, as follows.
Widget _buildSuggestions(){
_suggestions.addAll(generateWordPairs().take(20));
return new ListView.builder(
itemBuilder: (context,i){
if(i < _suggestions.length){
return_buildRow(_suggestions[i]); }}); }Copy the code
Now it works fine.
Now we want to add a line to each column of the list. In this case, we also add a line to the ListView as a row.
Widget _buildSuggestions(){
_suggestions.addAll(generateWordPairs().take(20));
return new ListView.builder(
itemBuilder: (context,i){
if(i.isOdd){returnnew Divider(); } row final index = I ~/ 2; // I is 0, 1, 2, 3, 4, 5... Index = 0, 0, 1, 1, 2, 2... // Index is computed mainly because the iterator iterates twice as many times as before, half of which is to render the splitter and half of which is to render the row with dataif(index < _suggestions.length){
return_buildRow(_suggestions[index]); }}); }Copy the code
interactions
Here we add a heart shape to each row, which is like a “like” or “unlike” effect. First OF all, I’m going to create a Set to hold the words that we’ve liked. Set doesn’t allow duplicate data, which is better than List.
final _saved = new Set<WordPair>();
Copy the code
Add a heart shape to each row and declare an aleardySaved to determine if it was liked.
Widget _buildRow(WordPair pair){ final aleardySaved = _saved.contains(pair); // Check whether the current word is included, check whether it is likedreturn new ListTile(
title: new Text(
pair.asPascalCase,
style: _fontSize,
),
trailing: new Icon(
aleardySaved ? Icons.favorite : Icons.favorite_border,
color: aleardySaved ? Colors.red:null,
),
);
}
Copy the code
Clicking has no effect at this point, and you need to add click events to each row.
Widget _buildRow(WordPair pair){ final aleardySaved = _saved.contains(pair); // Check whether the current word is included, check whether it is likedreturn new ListTile(
title: new Text(
pair.asPascalCase,
style: _fontSize,
),
trailing: new Icon(
aleardySaved ? Icons.favorite : Icons.favorite_border,
color: aleardySaved ? Colors.red:null,
),
onTap: () => _favourite(pair),
);
}
void _favourite(WordPair pair){
setState((){
if(_saved.contains(pair)){
_saved.remove(pair);
}else{ _saved.add(pair); }}); }Copy the code
Now to achieve the desired effect, click to make it red and save, click again to make it default and remove it from the set collection.
Jump to a new page
Add a button in the navigation bar of the page to jump to a new page. The Navigator manages the stack containing all the routes of the application. Pushing a route onto the stack displays the updated route to the new page, and pulling a route off the stack returns the route to the previous page.
return new Scaffold(
appBar: new AppBar(
title: new Text("Welcome to flutter"),
actions: <Widget>[new IconButton(icon: new Icon(Icons.list), onPressed: _pushNavi)],
),
body: _buildSuggestions()
);
Copy the code
void _pushNavi(){
Navigator.of(context).push(
new MaterialPageRoute(
builder:(context){
return new Scaffold(
appBar: new AppBar(
title: new Text("Welcome to new page"),
),
body: new Center(
child: new Text("new page"),),); })); }Copy the code
The effect is as follows: