The value of a tool lies in the person who uses it, not in the tool itself. There are many who can hold a pen, but few masters of painting. -- Zhang Fengjieteilie


Long less (doubt):Align so simple, what good to say. Jet: Can you hold a pen? Longshao: are you doubting my intelligence quotient? Let me show you:

Jet: Since you can hold a pen, draw one for me. Dragon: less… I suspect you’re hydrologic and I can prove it. Jet: You caught me. It’s not easy.


1. Align the source code

Jet: How do you usually use Align?

Long shao: how else can use, use the keyboard to type. Align has an alignment property that allows you to specify the relative position of a component in a container. Jet: Are you sure it’s an enumeration? Longshao: there are 9 types in total. What is not enumeration? (Enter Alignment source)

class AlignTest extends StatelessWidget { AlignTest({Key key}) :super(key: key); @override Widget build(BuildContext context) {var childBox = Container(// width: 40, height: 40, color: Colors.cyanAccent, ); Var childLayout = Align(// layout component Align: Align. Center, child: childBox,); Return Container(// Parent component width: 110, height: 68, color: Colors. Grey, Child: childLayout,); }}Copy the code

Long Shao: Huh? It’s a class, and the ones that look like enumerations are static constants. Jett: So the ability to align is not just nine alignments, it’s a kind of arrangement. Dragon less: so… What?

class Alignment extends AlignmentGeometry {
  ...
  static const Alignment topLeft = Alignment(-1.0, -1.0);
  static const Alignment topCenter = Alignment(0.0, -1.0);
  static const Alignment topRight = Alignment(1.0, -1.0);
  static const Alignment centerLeft = Alignment(-1.0, 0.0);
  static const Alignment center = Alignment(0.0, 0.0);
  static const Alignment centerRight = Alignment(1.0, 0.0);
  static const Alignment bottomLeft = Alignment(-1.0, 1.0);
  static const Alignment bottomCenter = Alignment(0.0, 1.0);
  static const Alignment bottomRight = Alignment(1.0, 1.0);
Copy the code

Jeter: This makes it easy to manipulate the position of the elements. Now there is a requirement that you are given a set of components to install the specified function curve layout. What do you do?

Long shao: Bring me the knife! Let me see which one of you is asking for… Jet: Calm down, calm down, first see how to complete the sin positioning component position. Here’s a Slider to illustrate how the data changes

Jet: First prepare a ball component, you can specify the size and color:

class Ball extends StatelessWidget { Ball({Key key, this.radius=15, this.color=Colors.blue,}) :super(key: key); final double radius; // radius final Color Color; // color @override Widget build(BuildContext context) {return Container(width: radius*2, height: radius*2, decoration: BoxDecoration( shape: BoxShape.circle, color: color, ), ); }}Copy the code

Long Shao: Huh? It’s funny. It’s really clever. Why do I want to beat you up

class SinLayout extends StatefulWidget { SinLayout({Key key,}) : super(key: key); @override _SinLayoutState createState() => _SinLayoutState(); } class _SinLayoutState extends State<SinLayout> {var _x=0.0; @override Widget build(BuildContext context) {var item= Container(width: 300, height: 200, color: Colors.black.withAlpha(10), child: Align( child: Ball(color: Colors.orangeAccent,), alignment: Alignment (_x, f (PI) _x *), / / < - according to _x linkage y, location),); Var slider= slider (Max: 180, min: -180, more information: ${_x. ToStringAsFixed (2)}π", value: _x*180, onChanged: (v) { setState(() {_x=v/180; }); // Update the abscissa while dragging}); return Column( mainAxisSize: MainAxisSize.min, children: <Widget>[slider, item], ); } double f(x) {// double y = sin(x); return y; }}Copy the code

Now wrap a sin image placement component

class SinPlace extends StatelessWidget { SinPlace({Key key, this.child,this.t=0}) : super(key: key); final Widget child; final double t; @override Widget build(BuildContext context) { return Container( child:Align( child: child, alignment: Alignment(t,g(t* PI)), //<-- x aligns y); } double g(t) {double y = 0.5*sin(t); return y; }}Copy the code

Using the Stack

class SinLayout extends StatelessWidget {
  SinLayout({Key key, this.items}) :super(key: key);
  
  final Map<double,Widget> items;

  @override
  Widget build(BuildContext context) => Stack(
      children: items.keys.toList().map((key)=>
        SinPlace(t: key,child: items[key],)).toList() ,
    );
}
Copy the code

Pass in items

Var items = < double, widgets > {- 0.2: CircleAvatar (backgroundImage: AssetImage (" images/caver. Jpeg "),), - 0.4: CircleAvatar (backgroundImage: AssetImage (" images/honor. PNG "),), - 0.6: CircleAvatar (backgroundImage: AssetImage (" images/caver. Jpeg "),), - 0.8: CircleAvatar (backgroundImage: AssetImage (" images/leaf. PNG "),), -1:CircleAvatar(backgroundImage:AssetImage("images/caver.jpeg") ,), 0:CircleAvatar(backgroundImage:AssetImage("images/icon_head.png") ,), 0.2: CircleAvatar (backgroundImage: AssetImage (" images/caver. Jpeg "),), 0.4: CircleAvatar (backgroundImage: AssetImage (" images/wy_200x300. JPG "),), 0.6: CircleAvatar (backgroundImage: AssetImage (" images/caver. Jpeg "),), 0.8: CircleAvatar (backgroundImage: AssetImage (" images/icon_head. PNG "),), 1:CircleAvatar(backgroundImage:AssetImage("images/caver.jpeg") ,), };Copy the code

As you can probably see, it’s just a function, so it can be even more powerful, and it can be wrapped up as a custom function graph arrangement. Construct the function from the form of the parametric equation, by f and g

typedef FunNum1=Function(double t ); class MathPlace extends StatelessWidget { MathPlace({Key key, this.child,this.t=0,this.f,this.g}) : super(key: key); final Widget child; final FunNum1 f; final FunNum1 g; final double t; @override Widget build(BuildContext context) { var result= Container( child:Align( child: child, alignment: Alignment(f(t),g(t)), //<-- x aligns y); return result; } } class MathLayout extends StatelessWidget { MathLayout({Key key, this.items,this.f,this.g}) :super(key: key); final FunNum1 f; final FunNum1 g; final Map<double,Widget> items; @override Widget build(BuildContext context) => Stack( children: items.keys.toList().map((key)=>MathPlace(t: key,child: items[key],f: f,g: g,)).toList() , ); }Copy the code

Circular arrangement, easy

Container(
    width: 350,
    height: 350,
    child: MathLayout(
            items: items,
            f: (t) => cos(t * pi),
             g: (t) => sin(t * pi),
))
Copy the code

Ellipse arrangement, easy

Container(width: 350, height: 350, Child: MathLayout(items: items, F: (t) => 0.8*sin(t * PI), g: (t) => 0.6*cos(t * PI),,,Copy the code

Longshao: Well, I’m going to relearn math in primary school. (Manual laughing and crying)


This is the end of this article. If you want to taste Flutter quickly, Flutter For Seven days is a must-have. If you want to explore it, follow in my footsteps and complete a Flutter tour. In addition, I have a Flutter wechat communication group. You are welcome to join and discuss Flutter issues together. My wechat account is ZDL1994328.

Full of absurd words, a bitter tears. All the authors are crazy, who solve the taste.