Preface:
This is the sixth day of my participation in the August More text Challenge. For details, see: August More Text Challenge. To prepare for the August challenge of the nuggets, I’m going to pick 31 components this month that haven’t been introduced before and do a full analysis and attribute introduction. These articles will be used as important material in the collection of the Flutter components. I hope I can stick to it, your support will be my biggest motivation ~
- 1. [Flutter component collection] NotificationListener | August more text challenge
- 2.【Flutter Components 】Dismissible | August more challenges
- 3.【Flutter Component Collection 】 How the Switch was made | August More text Challenge
- 4.【Flutter Component Collection 】Scrollbar | August more text challenge
- 5. ClipPath | August
- 6. The Flutter components checked 】 CupertinoActivityIndicator | August more challenges
[this article]
The use of a, CupertinoActivityIndicator
May see CupertinoActivityIndicator components, someone will: is it not a iOS turn style of chrysanthemum, to use such a simple object, what to say ah, it seems that you also want to water. CupertinoActivityIndicator in my mind is a textbook level component, it provides a very much components related knowledge points, such as animation, drawing, the use of State lifecycle callback, it is very worthy of study, analysis and taste.
1. CupertinoActivityIndicator properties
CupertinoActivityIndicator use is very simple, ordinary structure has only two parameters:
The property name | type | The default value | use |
---|---|---|---|
animating | bool | true | Indicates whether to animate |
radius | double | 10 | Indicates the radius of the indicator |
The following are two CupertinoActivityIndicator properties using small case, on the left side of the radius of 15, and animating set to true, so in spinning, for loading. If the right radius is 20 and animating is set to false, it is static.
class CupertinoActivityIndicatorDemo extends StatelessWidget {
const CupertinoActivityIndicatorDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 40,
children:[
CupertinoActivityIndicator(
animating: true,
radius: 15,
),
CupertinoActivityIndicator(
animating: false,
radius: 20,)]); }}Copy the code
2. CupertinoActivityIndicator partiallyRevealed structure
In addition to the normal construct, there is a partiallyRevealed construct, which, as you can see from the definition below, has only radius and progress properties. And animating is fixed to false, indicating that the construct is a static effect of the specified progress.
Progress (0 ~ 1);
class CupertinoActivityIndicatorDemo extends StatelessWidget {
const CupertinoActivityIndicatorDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 20,
children: List.generate(
10,
(index) => CupertinoActivityIndicator.partiallyRevealed(
progress: 0.1 * index,
radius: 15, ), ).toList()); }}Copy the code
Second, CupertinoActivityIndicator source points
1. CupertinoActivityIndicator component source is introduced
CupertinoActivityIndicator inherited from StatefulWidget, says it has internal demand status updates. There are three members defined for component information configuration, and these three properties are also described in the usage above. As a StatefulWidget, its components to build the logic of the classes will be passed on to the corresponding state, this is _CupertinoActivityIndicatorState.
From _CupertinoActivityIndicatorState can be seen in the class structure, component depends on the construction of a SizedBox and CustomPaint. And override the callback methods for the three State lifecycles.
2. Animation processing
CupertinoActivityIndicator since can undertake loading rotation, the inevitable need for animation. As follows, _CupertinoActivityIndicatorState mixed with SingleTickerProviderStateMixin, instantiation AnimationController in initState, Here we can see that when widget.animating is true, the animator controller will immediately repeat for 1 second.
Release the _controller in the Dispose callback.
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Copy the code
3. DidUpdateWidget callback
Maybe a lot of people are not very clear about the role of this callback. When the component is rebuilt, the state class is not reinitialized. Instead, the didUpdateWidget is called back to compare the configuration information between the new and old widgets for response logic processing. There are many ways to make components rebuild, such as setState, ValueListenableBuilder, FutrueBuilder, etc., which are essentially setStates.
@override
void didUpdateWidget(CupertinoActivityIndicator oldWidget) {
super.didUpdateWidget(oldWidget);
if(widget.animating ! = oldWidget.animating) {if (widget.animating)
_controller.repeat();
else_controller.stop(); }}Copy the code
What happens if you don’t handle the didUpdateWidget? Such as through the Switch to Switch CupertinoActivityIndicator animating properties, CupertinoActivityIndicator rebuild, if there is no didUpdateWidget processing, The state class is not aware of changes in the widget’s configuration information, and therefore cannot switch whether to animate or not.
4. Processing of drawing
In the build method, using SizedBox component size limit, drawn by _CupertinoActivityIndicatorPainter.
A long time ago, when setState was the only way to trigger a drawing of the artboard, I always had a problem with this, because setState updating the artboard would cause the artboard object to be recreated, which was very unfriendly to draw an animation because it was triggered so often. It was not until I read CupertinoActivityIndicator source code, there is a new cognitive redrawn to the drawing board. This clears the final hurdle for “The Guide to Drawing Flutter: A Great Pen.”
Is see CupertinoActivityIndicator does not use setState, can perform an animation to update internal state, this is to let a person very excited. After a little testing, the secret is super(repaint: Position). The artboard can trigger a redraw with a Listenable object without triggering the build of any components. The underlying rationale for this implementation is detailed source code analysis in the Flutter Drawing Exploration column.
The specific drawing logic is also very simple, is to iterate the rotation to draw a rounded rectangle.
4. CupertinoActivityIndicator color
Can be seen from the source of CupertinoActivityIndicator colors are fixed, users can’t directly set. But in the dark/light mode, the colors are different, as follows:
The activeColor is handled according to the dark/light mode. Here, in dark mode, it appears slightly white. If we want our own component to support the dark/light mode, we can do the same.
Three, CupertinoActivityIndicator attention point
There’s one caveat. For example, I through the Wrap package CupertinoActivityIndicator and another CustomPaint, through BoxPainter draw a square.
class CupertinoActivityIndicatorDemo extends StatelessWidget {
const CupertinoActivityIndicatorDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Wrap(
spacing: 20,
children: [
CupertinoActivityIndicator(
animating: true,
radius: 15,
),
CustomPaint(
size: Size(50.50), painter: BoxPainter(), ) ], ); }}class BoxPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
print('-------BoxPainter----------');
canvas.drawRect(Offset.zero & size, Paint());
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false; }}Copy the code
Through the log can be found BoxPainter as CupertinoActivityIndicator animation to redraw. Can someone will be very confused, clearly BoxPainter does not need to be redrawn, why would have been drawn, CupertinoActivityIndicator too garbage.
This is not an exception, it is essentially a RepaintBoundary mechanism. By looking at the render tree with the debugDumpRenderTree() method, you can see that both of them are in the same render area, as shown below they are both in UP7. Redrawing a node in the same render area will redraw all render nodes in that area. You can have multiple child components like Wrap, Column, Row, SingleChildScrollView, and Stack, all of which are rendered on the same layer.
We can through RepaintBoundary CupertinoActivityIndicator corresponding rendering object is separated, so as not to affect other nodes. Note that this is not CupertinoActivityIndicator problems of its own, is RepaintBoundary mechanism.
Wrap(
spacing: 20,
children: [
RepaintBoundary( //<----
child: CupertinoActivityIndicator(
animating: false,
radius: 15,
),
),
CustomPaint(
size: Size(50.50),
painter: BoxPainter(),
),
],
),
Copy the code
CupertinoActivityIndicator components used here are introduction, although is a simple widget, but the sparrow is small all-sided. It is worth studying and learning. That’s the end of this article. Thanks for watching. See you tomorrow