前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[-Flutter趣玩篇-] 出神入化的Align

[-Flutter趣玩篇-] 出神入化的Align

作者头像
张风捷特烈
发布2020-04-30 14:50:28
5290
发布2020-04-30 14:50:28
举报

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


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

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


1.Align的源码

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

代码语言:javascript
复制
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?

代码语言:javascript
复制
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演示一下数据变化时的效果

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

代码语言:javascript
复制
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,
      ),
    );
  }
}

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

代码语言:javascript
复制
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图像的位置摆放组件

代码语言:javascript
复制
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进行摆放

代码语言:javascript
复制
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传入即可

代码语言:javascript
复制
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

代码语言:javascript
复制
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() ,
  );
}

圆形排布,小意思

代码语言:javascript
复制
Container(
    width: 350,
    height: 350,
    child: MathLayout(
            items: items,
            f: (t) => cos(t * pi),
             g: (t) => sin(t * pi),
))

椭圆排布,好说

代码语言:javascript
复制
Container(
    width: 350,
    height: 350,
    child: MathLayout(
      items: items,
      f: (t) => 0.8*sin(t * pi),
      g: (t) => 0.6*cos(t * pi),
    )),
,

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年09月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Align的源码
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档