【布局 widget】Flutter Stack

简介: 【布局 widget】Flutter Stack

image.png


当你想叠放一些组件的时候, stack 组件非常有用。相当于 web 中 的 relativeabsolute 定位产生的效果。

为了方便说明,约定 stack 有两种子组件,定位子组件和非定位子组件,区别就是是否被有定位属性的Positioned 包起来。

// 非定位组件
Stack( children:[ const Text('hello')]) 
// 非定位组件,Positioned 为没有定位属性,会被忽略。
Stack( children:[ const Positioned( child: Text('hello'))])
// 定位组件
Stack( children:[ const Positioned( left: 0, child: Text('hello'))])
复制代码

Stack 组件的大小

如果父级传过来的是 tight 约束,那么 Stack 就不再考虑子组件的尺寸,Stack 的大小就是 tight 约束的大小。

如果 是 loose 约束,有两种情况:

  1. 如果 Stack 只有定位组件,那么 Stack 会倾向于最大。
  2. 如果 Stack 有非定位组件,那么它会尝试缩小自己,让自己能 wrap 所有非定位组件。

比如下面的 stack 会尽量缩小自己,Positioned 没有定位属性,也属于非定位组件。

Center(
      child: Stack(alignment: AlignmentDirectional.bottomCenter, children: [
        Positioned(
            child: Container(
              color: Colors.green,
          height: 100,
          width: 100,
        ))
      ]),
 )
复制代码

在没有约束且只有定位组件的情况下,stack 会报错。比如下面的例子就会报错。

UnconstrainedBox(
    child: Stack(
          children: const [
            Positioned(left: 0, child: Text('hello')),
        ],
))
复制代码

子组件绘制顺序

image.png


Stack(
 children: [
   Container(width: 160,height: 160,color: Colors.blue,),
   Container(width: 140,height: 140,color: Colors.red,),
   Container(width: 120,height: 120,color: Colors.green,),
],)
复制代码

前面的子组件最先绘制,所以看起来在最底下。

如果把一个定位子组件排在第 4 位,那么它就会排在第 4 个绘制。在绘制顺序上定位组件和非定位组件没有差别。

子组件对齐方式

子组件默认的定位方式是 topLeft,可以通过 alignment 参数修改。

Stack(
   alignment: Alignment.center,
   ...
复制代码

如果你指定了alignment却没有效果,可能是因为 Stack 和子组件一样大

如果把 其中的 Containter 换成 Positioned(child:Container) 效果一样,同样受 alignment属性控制。因为 Positioned 没有定位属性。

子组件的大小

Stack 默认给非定位子组件的约束是 loose,fit: StackFit.loose,在允许范围内子组件可以自己决定大小。

Stack 也可以传给非定位子组件 tight 约束,fit: StackFit.expand 这时非定位子组件大小不能自己决定,而是直接充满整个 Stack。

fit 的可选值还有一个 StackFit.passthrough。这个时候, Stack 把父约束透传给子组件。

定位子组件的大小

定位子组件比较超然,不受fit 值的影响。

定位子组件是以 Stack 的左上角为原点计算 x,y值。

定位子组件的大小与 top,bottom,left,right,width,height 这几个值有关。

满足下面两条 定位子组件 获得 tight 约束

  1. 同时指定 top,bottom,或单独指定 height
  2. 同时指定 left,right,或单独指定 width

根据 top,bottom 可以得出 height = child.size.height-top-bottom

根据 left,right 可以得出  width = child.size.width-left-right

如果不满足上面两条,子组件就彻底放飞了,没有约束。

比如下面的蓝块因为只有bottom一个值,所以没有约束,除了下面,其它三面可以无限延伸。


image.png


Center(child: Stack(
        clipBehavior: Clip.none,
        alignment: Alignment.bottomCenter,
        children: [
          Container(
            color: Colors.green,
            width: 300,
            height: 100,
          ),
          Positioned(
            bottom: 0,
              child: Container(
                    color: Colors.blue,
                    height: 200,
                    width: 150,
                  )
              )
        ],
      ),
    )
复制代码

IndexedStack

IndexedStack 是 Stack 的子类,和 Stack 唯一不同的是 IndexedStack 只绘制 index 属性指定的 child,而不是绘制所有 child. 其它都一样。

RenderIndexedStack 类 override paintStack 方法,从默认的绘制所有子组件,修改成只绘制当前组件。

@override
  void paintStack(PaintingContext context, Offset offset) {
    if (firstChild == null || index == null) {
      return;
    }
    //找到 index 属性指定的 child 只绘制这一个
    final RenderBox child = _childAtIndex();
    final StackParentData childParentData = child.parentData! as StackParentData;
    context.paintChild(child, childParentData.offset + offset);
  }
复制代码

参考

目录
相关文章
|
1天前
|
编解码 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的响应式设计与自适应布局
【4月更文挑战第30天】Flutter框架助力移动应用实现响应式设计与自适应布局,通过层次化布局系统和`Widget`树管理,结合`BoxConstraints`定义尺寸范围,实现自适应。利用`MediaQuery`获取设备信息,调整布局以适应不同屏幕。`FractionallySizedBox`按比例设定尺寸,`LayoutBuilder`动态计算布局。借助这些工具,开发者能创建跨屏幕尺寸、方向兼容的应用,提升用户体验。
【Flutter前端技术开发专栏】Flutter中的响应式设计与自适应布局
|
1天前
|
开发框架 前端开发 数据安全/隐私保护
【Flutter 前端技术开发专栏】Flutter 中的布局与样式设计
【4月更文挑战第30天】本文探讨了Flutter的布局和样式设计,关键点包括:1) 布局基础如Column、Row和Stack用于创建复杂结构;2) Container、Center和Expanded等常用组件的作用;3) Theme和Decoration实现全局样式和组件装饰;4) 实战应用如登录界面和列表页面的构建;5) 响应式布局利用MediaQuery和弹性组件适应不同屏幕;6) 性能优化,避免过度复杂设计。了解并掌握这些,有助于开发者创建高效美观的Flutter应用。
【Flutter 前端技术开发专栏】Flutter 中的布局与样式设计
|
1天前
|
开发框架 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
【4月更文挑战第30天】探索Flutter的自定义Widget与渲染流程。自定义Widget是实现复杂UI设计的关键,优点在于个性化设计、功能扩展和代码复用,但也面临性能优化和复杂性管理的挑战。创建步骤包括设计结构、定义Widget类、实现构建逻辑和处理交互。Flutter渲染流程涉及渲染对象树、布局、绘制和合成阶段。实践案例展示如何创建带渐变背景和阴影的自定义按钮。了解这些知识能提升应用体验并应对开发挑战。查阅官方文档以深入学习。
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
|
1天前
|
JavaScript 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
【4月更文挑战第30天】本文探讨了Flutter的Widget和状态管理。Widget是Flutter构建UI的基础,分为有状态和无状态两种。状态管理确保UI随应用状态变化更新,影响应用性能和可维护性。文章介绍了`setState`、`Provider`、`Riverpod`、`Bloc`和`Redux`等状态管理方法,并通过计数器应用展示了其实现。选择合适的状态管理策略对高效开发至关重要。
【Flutter前端技术开发专栏】Flutter中的Widget与状态管理
|
1天前
|
前端开发 开发者 UED
Flutter的自定义Painter:深入探索自定义绘制Widget的技术实现
【4月更文挑战第26天】Flutter的自定义Painter允许开发者根据需求绘制独特UI,通过继承`CustomPaint`类和重写`paint`方法实现。在`paint`中使用`Canvas`绘制图形、路径等。创建自定义Painter类后,将其作为`CustomPaint` Widget的`painter`属性使用。此技术可实现自定义形状、渐变、动画等复杂效果,提升应用视觉体验。随着Flutter的进化,自定义Painter将提供更丰富的功能。
|
1天前
|
编解码 算法 开发者
Flutter的布局系统:深入探索布局Widget与布局原则
【4月更文挑战第26天】Flutter布局系统详解,涵盖布局Widget(Row/Column、Stack、GridView/ListView、CustomSingleChildLayout)和布局原则(弹性布局、约束优先、流式布局、简洁明了)。文章旨在帮助开发者理解并运用Flutter的布局系统,创建适应性强、用户体验佳的界面。通过选择合适的布局Widget和遵循原则,可实现复杂且高效的UI设计。
|
1天前
|
开发框架 搜索推荐 Android开发
Flutter的Widget基础:概念、分类与深入探索
【4月更文挑战第26天】Flutter Widget详解:基础、分类与工作原理。Widget是Flutter UI的核心,描述界面外观而非直接渲染。分为基础、布局、可滚动及状态管理四大类。基于响应式编程,状态变化时自动更新UI。了解其概念、分类和原理,能助开发者高效构建精美应用。随着Flutter生态发展,Widget系统潜力无限。
|
1天前
|
容器
Flutter笔记:Box协议的布局约束原理与应用
Flutter笔记:Box协议的布局约束原理与应用
49 0
|
1天前
|
开发者 索引 容器
Flutter开发笔记:Flutter 布局相关组件
Flutter开发笔记:Flutter 布局相关组件
138 0
|
8月前
|
Dart 前端开发 开发工具
谷歌移动UI框架Flutter教程之Widget
谷歌移动UI框架Flutter教程之Widget

热门文章

最新文章