【布局 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);
  }
复制代码

参考

目录
相关文章
|
28天前
|
缓存 监控 前端开发
优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面
本文探讨了优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面,并通过案例分析展示了具体措施和效果,强调了持续优化的重要性及未来优化方向。
54 10
|
2天前
|
存储 容器
Flutter 构建自适应布局
Flutter 构建自适应布局
Flutter 构建自适应布局
|
2天前
|
容器
Flutter Widget 解析
Flutter Widget 解析
|
27天前
|
开发框架 数据安全/隐私保护 开发者
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计,涵盖布局基础、常用组件、样式设计、实战应用、响应式布局及性能优化等方面,助力开发者打造精美用户界面。
41 7
|
2天前
|
存储 容器
Flutter 有状态Widget 和 无状态Widget
Flutter 有状态Widget 和 无状态Widget
|
1月前
深入理解Flutter鸿蒙next版本 中的Widget继承:使用extends获取数据与父类约束
本文详细介绍了Flutter中如何通过继承其他Widget来创建自定义组件。首先解释了Widget继承的基本概念,包括StatelessWidget和StatefulWidget的区别。接着通过具体示例展示了如何继承StatelessWidget和StatefulWidget,并在子类中访问父类的build方法和状态。最后,结合多个自定义Widget展示了如何在实际应用中灵活使用继承和组合来构建复杂的UI。
76 8
|
1月前
|
开发者 容器
Flutter&鸿蒙next 布局架构原理详解
本文详细介绍了 Flutter 中的主要布局方式,包括 Row、Column、Stack、Container、ListView 和 GridView 等布局组件的架构原理及使用场景。通过了解这些布局 Widget 的基本概念、关键属性和布局原理,开发者可以更高效地构建复杂的用户界面。此外,文章还提供了布局优化技巧,帮助提升应用性能。
104 4
|
1月前
|
容器
flutter&鸿蒙next 使用 InheritedWidget 实现跨 Widget 传递状态
在 Flutter 中,状态管理至关重要。本文详细介绍了如何使用 InheritedWidget 实现跨 Widget 的状态传递。InheritedWidget 允许数据在 Widget 树中向下传递,适用于多层嵌套的场景。通过一个简单的计数器示例,展示了如何创建和使用 InheritedWidget,包括其基础概念、工作原理及代码实现。虽然 InheritedWidget 较底层,但它是许多高级状态管理解决方案的基础。
103 2
|
1月前
|
容器
Flutter &&鸿蒙next中的 Stack 和 Positioned 用法详解
在 Flutter 中,Stack 和 Positioned 是创建层叠布局和灵活定位元素的常用组件。Stack 可以将多个子组件叠加在一起,允许子组件相互重叠;Positioned 用于在 Stack 内部精确控制子组件的位置。本文详细介绍了它们的基本用法、属性和应用场景,包括动画、弹出层和悬浮按钮等。
98 1
|
1月前
|
容器
深入理解 Flutter 鸿蒙版的 Stack 布局:适配屏幕与层叠样式布局
Flutter 的 Stack 布局组件允许你将多个子组件层叠在一起,实现复杂的界面效果。本文介绍了 Stack 的基本用法、核心概念(如子组件层叠、Positioned 组件和对齐属性),以及如何使用 MediaQuery 和 LayoutBuilder 实现响应式设计。通过示例展示了照片展示与文字描述、动态调整层叠布局等高级用法,帮助你构建更加精美和实用的 Flutter 应用。
137 2