Introduction
All components in flutter are composed of widgets, and there are various widgets in flutter, and these widgets constitute the edifice of flutter.
So what are the characteristics of widgets in flutter? How should we learn widgets? Let's take a look together.
StatelessWidget and StatefulWidget
In real time, widgets in flutter are inspired by React. The widgets in flutter can be divided into StatefulWidget and StatelessWidget, which represent stateful widgets and stateless widgets respectively.
Stateful and stateless, do you sound familiar? We often use stateful beans and stateless beans in our applications. Their principles are similar to those of flutter's two types of widgets.
Because the StatelessWidget is stateless, it will only build the Widget based on the initial configuration information passed in. Because the Widget is immutable, the StatelessWidget will not change after it is created.
For StatefulWidget, in addition to creating a Widget according to the initial incoming configuration, it also contains a State inside. This State is used to interact with the user's behavior to modify the values in the State. When the State is modified, the Widget bound to it will be compared according to a specific algorithm to see if it needs to be redrawn, so as to reflect the user's interaction on the user interface.
The widget provides a build method that returns a Widget for generating the final RenderObject object.
The build method is defined as follows:
Widget build(BuildContext context);
But in fact, the build method is only available in StatelessWidget. So why doesn't StatefulWidget have a build method?
Although StatefulWidget does not have a build method, it has a createState method to create the State associated with it:
State createState();
And this build method is placed in the State.
Detailed explanation of StatelessWidget
What kind of components can be made stateless components? Components that do not need to interact with the user will do.
What are the stateless widgets in flutter?
Here are a few basic and frequently used StatelessWidgets in flutter:
Text: Used to create text.
Row and Column: Represents vertical and horizontal expansion of rows and columns. Row and Column are web-based flexbox layouts.
There is also a web-based absolutely positioned layout called Positioned, which is usually used with Stack.
Stack is the structure of a stack. In Stack, you can place a widget on top of another widget.
Positioned is used in Stack, which can be relatively positioned relative to the top, right, bottom or left boundary, which is very useful.
Another commonly used component is Container, which represents a rectangular element. Container can be decorated with BoxDecoration to represent background, border and shadow.
Containers can also contain features such as margins, padding and size constraints.
Next, let's use a specific example to illustrate how StatelessWidget is used.
Suppose we want to build an interface of the following style, how do we do it?
This interface can be divided into two parts, the upper one is generally called appBar, and the lower one is generally called content.
The layout of the appBar can be divided into three parts. The first part is an IconButton representing the navigation menu, the second part is a Text representing the page title, and the third part is also an IconButton representing the search button. These three parts are combined according to Row.
Then according to the construction principle of Flutter's widget, we can build the appBar into a Widget. Because the behavior of this Widget is only related to the initialization state, it can be set to StatelessWidget:
class MyAppBar extends StatelessWidget {
const MyAppBar({required this.title, Key? key}) : super(key: key);
final Widget title;
@override
Widget build(BuildContext context) {
return Container(
height: 56.0, // bar的高度
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(color: Colors.blue[500]),
// 按Row来进行布局
child: Row(
children: [
const IconButton(
icon: Icon(Icons.menu),
tooltip: '导航菜单',
onPressed: null, // 目前不可点击
),
// Expanded组件,用于填充所有可用的空间
Expanded(
child: title,
),
const IconButton(
icon: Icon(Icons.search),
tooltip: '搜索',
onPressed: null,
),
],
),
);
}
}
In the above code, we include the Row in a Container, and then return this Container as the actual content of the appBar.
The lower part of the UI is relatively simple, which is a centered Text. We combine it with the appBar, put it in a Column, and divide it by row:
class MyScaffold extends StatelessWidget {
const MyScaffold({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Material(
// 构建一个两行的column,一个是bar, 一个是具体的内容
child: Column(
children: [
MyAppBar(
title: Text(
'StatelessWidget',
textAlign: TextAlign.center,
style: Theme.of(context)
.primaryTextTheme
.headline6,
),
),
const Expanded(
child: Center(
child: Text('这是一个Text组件!'),
),
),
],
),
);
}
}
It is also a StatelessWidget, which returns the Material widget in the build method.
Then, we wrap MyScaffold in a MaterialApp as the final returned MyApp:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// 这是应用程序的根widget
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '第一个StatelessWidget',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const SafeArea(
child: MyScaffold(),
),
);
}
}
Finally, run MyApp in the runApp method:
void main() {
runApp(const MyApp());
}
Detailed StatefulWidget
Above we explained a method of how to use StatelessWidget to construct an app. You should be familiar with the basic process.
It should be noted here that StatelessWidget does not mean that no variables can be stored in the widget. As shown in the above example, the StatelessWidget of MyAppBar is actually a widget containing a title, but this widget is final, that is to say, it is defined once. It cannot be changed, so it is called StatelessWidget.
The difference between StatefulWidget and StatelessWidget is that StatefulWidget can be associated with a State. State can contain some variable properties, which can interact with user operations to complete some more complex functions.
If we need an interface below, there is a button at the bottom right of the interface. Click once to increase the number in the middle by one.
This is an obvious behavior to interact with the user. Here we can use StatefulWidget.
Here we create a StatefulWidget of MyHomePage, and create a state of _MyHomePageState to associate with it:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
Note that mutable properties are stored in the state associated with the StatefulWidget, not the StatefulWidget itself.
So we need to define an int _counter variable in _MyHomePageState to store the number of user clicks. Then define a _incrementCounter to accumulate _counter.
In _incrementCounter, you need to call the setState method to refresh the state of the State.
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Then in the build method in State, you can return the Widget corresponding to the UI. Here we use the Scaffold component, which comes with appBar and body:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'按钮被点了:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
const Text(
'次',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
Here in the body, we choose to use the Center component to display content information. The floating button uses FloatingActionButton, and its onPressed method will trigger the _incrementCounter method we wrote earlier to increase _counter by one.
Finally, pass the component we built into MaterialApp as follows:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// 根Widget
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '第一个StatefulWidget',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MyHomePage(title: 'StatefulWidget'),
);
}
}
Summarize
Above, we briefly explained the simple usage of StatelessWidget and StatefulWidget. We will go deeper into these components in the future, so stay tuned.
The code of this article can refer to: https://github.com/ddean2009/learn-flutter , if you think it is good, please like it, thank you.
For more information, please refer to http://www.flydean.com/02-flutter-widget/
The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。