为了账号安全,请及时绑定邮箱和手机立即绑定

[-Flutter趣玩篇-] Align-Alignment 知多少

标签:
WebApp

工具的价值在于使用它的人,而非工具自身。会拿笔的人很多,但绘画宗师寥寥无几。--张风捷特烈


龙少(疑惑):Align这么简单,有什么好讲的。
捷特: 你会拿笔吗?
龙少:你是在怀疑我的智商?我拿给你看:


https://img1.sycdn.imooc.com//5d89dd7d0001c9e206670315.jpg


捷特: 既然会拿笔,给我画一张。
龙少: ...,我怀疑你在水文,而且我证据确凿。
捷特: 这都被你发现了,水一页可真不容易。



https://img1.sycdn.imooc.com//5d89dd940001e2b606530416.jpg
1.Align的源码

捷特: 你平时怎么用Align?
龙少: 还能怎么用,用键盘敲呗。Align中有一个alignment属性,通过Alignment枚举,可以指定一个组件在容器中的相对位置,虽然挺好用,但也没什么要点,你确定能水一篇?
捷特: 你确定是枚举。
龙少: 一共就9种类型,不是枚举是什么? (进入Alignment源码)

https://img1.sycdn.imooc.com//5d89ddde000142af06520288.jpg



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(//布局组件Align

      alignment: Alignment.center,

      child: childBox,

    );

    

    return Container(//父亲组件

      width: 110,

      height: 68,

      color: Colors.grey,

      child: childLayout,

    );

  }

}


龙少: 嗯?居然是一个类,而且那些疑似枚举的都是静态常量。
捷特: so,Alignment的能力并非仅是九种对齐方式,它是一种排布。
龙少: so... what?

https://img1.sycdn.imooc.com//5d89ddf40001644706610233.jpg



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);


捷特: 这样就能很容易操纵元素的位置,现在有个需求,给你一批组件,让他们安装指定的函数曲线排布,你该怎么办?
龙少: 把刀拿来!我看看是哪个不走心的提的需求...
捷特: 淡定淡定,先看如何完成sin定位组件位置。这里用一个Slider演示一下数据变化时的效果

https://img1.sycdn.imooc.com//5d89de37000198cf06640306.jpg

捷特: 先准备一个小球组件,可指定大小和颜色:

class Ball extends StatelessWidget {

  Ball({Key key, this.radius=15, this.color=Colors.blue,}) :super(key: key);

  final double radius; //半径

  final Color color; //颜色


  @override

  Widget build(BuildContext context) {

    return Container(

      width: radius*2,

      height: radius*2,

      decoration: BoxDecoration(

        shape: BoxShape.circle,

        color: color,

      ),

    );

  }

}


龙少: 嗯?有点意思,确实挺巧妙,为什么有种想打你一顿的冲动

class SinLayout extends StatefulWidget {

  SinLayout({Key key,}) : super(key: key);

  @override

  _SinLayoutState createState() => _SinLayoutState();

}


class _SinLayoutState extends State<SinLayout> {

  var _x=0.0;//Alignment坐标系上的x坐标


  @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(_x*pi)), //<--- 根据_x联动y,确定位置

      ),

    );


    var slider=Slider(

        max: 180,

        min: -180,

        divisions:360,

        label: "${_x.toStringAsFixed(2)}π",

        value: _x*180,

        onChanged: (v) {

          setState(() {_x=v/180;});//拖动时更新横坐标

        });

    return Column(

      mainAxisSize: MainAxisSize.min,

      children: <Widget>[slider, item],

    );

  }


  double f(x) {//映射函数 -- 可随意指定

    double y = sin(x);

    return y;

  }

}


现在封装一个sin图像的位置摆放组件

https://img1.sycdn.imooc.com//5d89deca0001159406570165.jpg

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联动y,确定位置

        ));

  }


  double g(t) {//映射函数 -- 可随意指定

    double y = 0.5*sin(t);

    return y;

  }

}

通过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() ,

    );

}

使用items传入即可

var items=<double,Widget>{

    -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") ,),

  };


也许你看出来了,其实就是一个函数而已,所以可以它还能更强大,完全可以封成个自定义函数图像排列。根据参数方程的形式来构造函数,通过f和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联动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() ,

  );

}


圆形排布,小意思

https://img1.sycdn.imooc.com//5d89dfab0001309906590318.jpg

Container(

    width: 350,

    height: 350,

    child: MathLayout(

            items: items,

            f: (t) => cos(t * pi),

             g: (t) => sin(t * pi),

))

椭圆排布,好说

https://img1.sycdn.imooc.com//5d89dff80001514306500263.jpg

Container(

    width: 350,

    height: 350,

    child: MathLayout(

      items: items,

      f: (t) => 0.8*sin(t * pi),

      g: (t) => 0.6*cos(t * pi),

    )),

,

龙少: 好吧,我要去小学重新学数学。(手动笑哭)


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
20
获赞与收藏
56

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 1
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消