Widget
Import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
MyAppBar({this.title});
// Fields in a Widget subclass are always marked "final".
final Widget title;
@override
Widget build(BuildContext context) {
return Container(
height: 56.0, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: Row(
// <Widget> is the type of items in the list.
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child to fill the available space.
Expanded(
child: title,
),
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}
class MyScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Material is a conceptual piece of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: <Widget>[
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context).primaryTextTheme.title,
),
),
Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}
void main() {
runApp(MaterialApp(
title: 'My app', // used by the OS task switcher
home: MyScaffold(),
));
}
- have a different lifespan: they are immutable and only exist until they need to be changed.
- Are lightweight, in part due to their immutability.
- Describe what their view should look like given their current configuration and state.
- When a widget’s state changes, the widget rebuilds its description, which the framework diffs against the previous description in order to determine the minimal changes needed in the underlying render tree to transition from one state to the next.
- A widget’s main job is to implement a build() function, which describes the widget in terms of other, lower-level widgets.
- The framework builds those widgets in turn until the process bottoms out in widgets that represent the underlying RenderObject, which computes and describes the geometry of the widget.
- The core of Flutter’s layout mechanism.
- Are temporary objects, used to construct a presentation of the application in its current state.
Text
Row
Column
Stack
Container
Material Components
Import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Flutter Tutorial',
home: TutorialHome(),
));
}
class TutorialHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Scaffold is a layout for the major Material Components.
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: Text('Example title'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: Center(
child: Text('Hello, world!'),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
child: Icon(Icons.add),
onPressed: null,
),
);
}
}
A Material app starts with the MaterialApp widget, which builds a number of useful widgets at the root of your app, including a Navigator, which manages a stack of widgets identified by strings, also known as “routes”.
GestureDetector
Class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('MyButton was tapped!');
},
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Engage'),
),
),
);
}
}
Most applications include some form of user interaction with the system. The first step in building an interactive application is to detect input gestures.
Many widgets use a GestureDetector to provide optional callbacks for other widgets. For example, the IconButton, RaisedButton, and FloatingActionButton widgets have onPressed() callbacks that are triggered when the user taps the widget.
ShoppingListItem
Class Product {
const Product({this.name});
final String name;
}
typedef void CartChangedCallback(Product product, bool inCart);
class ShoppingListItem extends StatelessWidget {
ShoppingListItem({Product product, this.inCart, this.onCartChanged})
: product = product,
super(key: ObjectKey(product));
final Product product;
final bool inCart;
final CartChangedCallback onCartChanged;
Color _getColor(BuildContext context) {
// The theme depends on the BuildContext because different parts of the tree
// can have different themes. The BuildContext indicates where the build is
// taking place and therefore which theme to use.
return inCart ? Colors.black54 : Theme.of(context).primaryColor;
}
TextStyle _getTextStyle(BuildContext context) {
if (!inCart) return null;
return TextStyle(
color: Colors.black54,
decoration: TextDecoration.lineThrough,
);
}
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(product.name, style: _getTextStyle(context)),
);
}
}
Widget follows a common pattern for stateless widgets.
T stores the values it receives in its constructor in final member variables, which it then uses during its build() function.
Keys
- Use keys to control which widgets the framework matches up with other widgets when a widget rebuilds.
- By default, the framework matches widgets in the current and previous build according to their runtimeType and the order in which they appear. With keys, the framework requires that the two widgets have the same key as well as the same runtimeType.
- Keys are most useful in widgets that build many instances of the same type of widget. For example, the ShoppingList widget, which builds just enough ShoppingListItem instances to fill its visible region:.
Global Keys
Related concepts
- StatelessWidget
- StatefulWidget
- Manipulating position and size
- Basic layout operations: Styling and aligning text
- Basic layout operations: Centering components
- Async UI: ProgressIndicator widget
- Basic layout operations: Setting container width
- Text widget
- Manipulating position and size: Rotating components
- Basic layout operations: Scaling components
- Manipulating position and size: Applying a linear gradient
- Manipulating text: Adjusting text spacing
- Manipulating text: Making inline formatting changes
- TextStyle
- Manipulating text: Creating text excerpts
- Layouts
- Row and Column
- ListView widget
- Activities and fragments
- ListView
- a “hint” or a placeholder text
- Form input: Validation errors
- Themes
- Themes: MaterialApp
- Navigator
- Debugging
- RunApp()
- Widget: Text
- Widget: Stack
- Widget: Container
- Container
- Layouts: Lay out a widget
- Sizing widgets: Expanded widget
- Common layout widgets
- Loading assets: Loading text assets
- Loading assets: Loading images
- Dealing with box constraints: Flex
- Widget: Material Components
- Widget: GestureDetector
- Widget: ShoppingListItem
- Widget: Keys
- Widget: Global Keys
- Common animation patterns: Shared element transition
- addListener
- AnimatedBuilder
- Combine a tween with an animation: animate the tween
- Hero animations
- Hero animations: Hero widget
- PhotoHero class
- Staggered Animations: Complete staggered animation
- Gesture detection and touch event handling
- Form input
- Dealing with box constraints