Flutter is on the rise. Yesterday, Google officially released Flutter1.7, which includes Android X support, some updates to the Play Store, some new and enhanced components, and some bug fixes.
In this article we will work together to develop a stunning list display with scrolling and animated backgrounds. Take a look at the renderings:
Train of thought
As the list scrolls, the vertical scrolling distance is obtained, and this value is converted into units of Angle to drive the gear rolling
Entrance to the file
Flutter projects all start with lib/main.dart:
import 'package:flutter/material.dart';
import 'demo-card.dart';
import 'items.dart';
import 'animated-bg.dart';
void main() => runApp(AnimationDemo());
class AnimationDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(title: 'List scrolling')); }}class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController _controller = new ScrollController();
List<DemoCard> get _cards =>
items.map((Item _item) => DemoCard(_item)).toList();
@override
Widget build(BuildContext context) {
returnScaffold( backgroundColor: Colors.black, appBar: AppBar(title: Text(widget.title)), body: Stack( alignment: AlignmentDirectional.topStart, children: <Widget>[ AnimatedBackground(controller: _controller), Center( child: ListView(controller: _controller, children: _cards), ) ], ), ); }}Copy the code
In the main.dart file, there are several imported files:
demo-card.dart
The card widget, the list is the widget of the loopitems.dart
The data presented by the card is in this file. In this project, we wrote some mock data, and the data of the real production project is more from HTTP requestanimated-bg.dart
Background gear widget
This file mainly uses some basic Flutter widgets. If you don’t know how to use Flutter widgets, please check the official website. In addition, please pay attention to the list rendering. We’ll say ScrollController _controller = new ScrollController(); To get the vertical scrolling distance
Mock data for the card
Dart: The children of the listView in main.dart are generated from the same six data sets as the children of the listView:
import 'package:flutter/material.dart';
class Item {
String name;
MaterialColor color;
IconData icon;
Item(this.name, this.color, this.icon);
}
List<Item> items = [
Item('one', Colors.amber, Icons.adjust),
Item('. ', Colors.cyan, Icons.airport_shuttle),
Item('叁', Colors.indigo, Icons.android),
Item('boss', Colors.green, Icons.beach_access),
Item('wu', Colors.pink, Icons.attach_file),
Item('land', Colors.blue, Icons.bug_report)
];
Copy the code
Three fields:
- Name The name on the left of the card
- Color Indicates the background color of the card
- Icon Indicates the icon on the right of the card
Card Widget
Dart: children: items.map((Item _item) => DemoCard(_item)).tolist (); Pass _item to DemoCard, which is the props in React or Vue. The difference is that the parameters to a flutter can be either anonymous or named. Here we use anonymous upload parameters. Take a look at how the card Widget receives parameters:
import 'package:flutter/material.dart';
import 'items.dart';
class DemoCard extends StatelessWidget {
DemoCard(this.item);
final Item item;
static final Shadow _shadow =
Shadow(offset: Offset(2.0.2.0), color: Colors.black26);
final TextStyle _style = TextStyle(color: Colors.white70, shadows: [_shadow]);
@override
Widget build(BuildContext context) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(
side: BorderSide(width: 1, color: Colors.black26),
borderRadius: BorderRadius.circular(32),
),
color: item.color.withOpacity(7.),
child: Container(
constraints: BoxConstraints.expand(height: 256),
child: RawMaterialButton(
onPressed: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(item.name, style: _style.copyWith(fontSize: 64)),
Icon(item.icon, color: Colors.white70, size: 72() [() [() [() [() [() [() }}Copy the code
React/Vue: StatelessWidget; StatelessWidget: React/Vue: StatelessWidget;
DemoCard(this.item);
final Item item;
Copy the code
Use the Card component to quickly restore a Card style
elevation
Parameter control card suspension heightshape
Parameter control card filletcolor
Parameter control card background,item.color.withOpacity(.7)
Make the background transparent by 30%
Then you use columns and rows to control the presentation of the layout
Background gear rotation
Take a look at the source code of the background component and explain one by one:
import 'package:flutter/material.dart';
class AnimatedBackground extends StatefulWidget {
AnimatedBackground({Key key, this.controller}) : super(key: key);
final ScrollController controller;
@override
_AnimatedBackgroundState createState() => _AnimatedBackgroundState();
}
class _AnimatedBackgroundState extends State<AnimatedBackground> {
get offset => widget.controller.hasClients ? widget.controller.offset : 0;
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: widget.controller,
builder: (BuildContext context, Widget child) {
return OverflowBox(
maxWidth: double.infinity,
alignment: Alignment(4.3),
child: Transform.rotate(
angle: offset / - 512.,
child: Icon(Icons.settings, size: 512, color: Colors.white), ), ); }); }}Copy the code
Dart. This controller is the ListView controller. We use widget.controller.offset to get the vertical scrolling distance. We need to constantly refresh the rotation Angle of the gear as the list scrolls, so we use the AnimatedBuilder component, which has two important parameters:
- The animation passes widget.controller to the animation
- Each time the Builder animation changes, the rendering is re-executed, which achieves the linkage effect
The OverflowBox component provides excellent control over the display position of the child components with alignment(anchor points). Here we used alignment(4, 3) to position the gears to the lower left of the screen. It’s the transform. rotate component that makes the gears work. Here we have an arc length formula: L=α (radians) × r(radius), so we use Angle: offset / -512
- Why 512, because of our gear
size: 512
- Why does it have a minus sign, so that we can have the gear rotate counterclockwise when we scroll up the list, and clockwise when we scroll down the list
Use the Widget
Space is limited, we can not explain the components used one by one, if you have questions, please go to the official website to check the usage
- MaterialApp
- Scaffold
- AppBar
- Stack
- Center
- ListView
- Card
- RawMaterialButton
- Column
- Row
- AnimatedBuilder
- OverflowBox
- Transform
- Icon
A link to the
This article can learn because a lot of knowledge, including: StatelessWidget/StatefulWidget create, create and use the local data, the list of display and control, vertical, horizontal layout, etc., want to see the effect of students can be directly run the source code
- The source address
- Blog Post
- Nuggets this article address