Flutter 布局类组件:流式布局(Wrap和Flow)

前言

把超出屏幕显示范围会自动折行的布局称为流式布局。Flutter中通过Wrap和Flow来支持流式布局,将Row换成Wrap后溢出部分则会自动折行。

Wrap

接口描述

Wrap({
    Key key,
    this.direction = Axis.horizontal,
    this.alignment = WrapAlignment.start,
    // 主轴方向子widget的间距
    this.spacing = 0.0,
    // 纵轴方向的对齐方式
    this.runAlignment = WrapAlignment.start,
    // 纵轴方向的间距
    this.runSpacing = 0.0,
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    List<Widget> children = const <Widget>[],
  })

代码示例

class WrapTest extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('流式布局-Wrap'),
      ),
      body: Container(
        child: Wrap(
          // 主轴(水平)方向间距
          spacing: 8.0,
          // 纵轴(垂直)方向间距
          runSpacing: 4.0,
          // 沿主轴方向居中
          alignment: WrapAlignment.center,
          children: <Widget>[
            Chip(
              avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('A'),),
              label: Text('HelloWorld'),
            ),

            Chip(
              avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('B'),),
              label: Text('WorldHello'),
            ),

            Chip(
              avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('T'),),
              label: Text('FlowWorld'),
            ),

            Chip(
              avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('J'),),
              label: Text('WarpHello'),
            ),

            Chip(
              avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('F'),),
              label: Text('Yes i do'),
            ),

          ],
        ),
      ),
    );
  }
}

FLow

一般很少会使用Flow,因为其过于复杂,需要自己实现子widget的位置转换,在很多场景下首先要考虑的是Wrap是否满足需求。Flow主要用于一些需要自定义布局策略或性能要求较高(如动画中)的场景。
Flow有如下优点

  1. 性能好;Flow是一个对子组件尺寸以及位置调整非常高效的控件,Flow用转换矩阵在对子组件进行位置调整的时候进行了优化:在Flow定位过后,如果子组件的尺寸或者位置发生了变化,在FlowDelegate中的paintChildren()方法中调用context.paintChild 进行重绘,而context.paintChild在重绘时使用了转换矩阵,并没有实际调整组件位置。
  2. 灵活;由于我们需要自己实现FlowDelegate的paintChildren()方法,所以我们需要自己计算每一个组件的位置,因此,可以自定义布局策略。

缺点

  1. 使用复杂。
  2. 不能自适应子组件大小,必须通过指定父容器大小或实现TestFlowDelegate的getSize返回固定大小。

接口描述

 Flow({
    Key key,
    @required this.delegate,
    List<Widget> children = const <Widget>[],
  })

代码示例

class FlowTest extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('流式布局-Flow'),
      ),
      body: Container(
        child: Flow(
          delegate: FlowDelegateTest(margin: EdgeInsets.all(10.0)),
          children: <Widget>[
            Container(width: 80.0, height: 80.0, color: Colors.red,),
            Container(width: 80.0, height: 80.0, color: Colors.green,),
            Container(width: 80.0, height: 80.0, color: Colors.blue,),
            Container(width: 80.0, height: 80.0, color: Colors.yellow,),
            Container(width: 80.0, height: 80.0, color: Colors.brown,),
            Container(width: 80.0, height: 80.0, color: Colors.purple,),
          ],

        ),
      ),
    );

  }
}

class FlowDelegateTest extends FlowDelegate {
  EdgeInsets margin = EdgeInsets.zero;
  FlowDelegateTest({this.margin});

  // Flow主要要重载这个函数,它的主要任务是确定每个子widget位置。
  // 由于Flow不能自适应子widget的大小,通过在getSize返回一个固定大小来指定Flow的大小。
  @override
  void paintChildren(FlowPaintingContext context) {
    var x = margin.left;
    var y = margin.right;
    // 计算每一个子widget的位置
    for(int i = 0; i < context.childCount; ++i) {
      var w = context.getChildSize(i).width + x + margin.right;
      if (w < context.size.width) {
        context.paintChild(
            i,
            transform: Matrix4.translationValues(x, y, 0.0)
        );
        x = w + margin.left;
      } else {
        x = margin.left;
        y += context.getChildSize(i).height + margin.top + margin.bottom;
        // 绘制子widget
        context.paintChild(
            i,
            transform: Matrix4.translationValues(x, y, 0.0)
        );
        x += context.getChildSize(i).width + margin.left + margin.right;
      }
    }
  }

  @override
  Size getSize(BoxConstraints constraints) {
    // 指定Flow的大小
    return Size(double.infinity, 200.0);
  }

  @override
  bool shouldRepaint(FlowDelegate oldDelegate) {
    return oldDelegate != this;
  }
}

原文地址:https://www.cnblogs.com/parzulpan/p/12071664.html

时间: 2024-08-29 16:53:34

Flutter 布局类组件:流式布局(Wrap和Flow)的相关文章

移动端布局学习之流式布局1

1.移动端基础 1.1 浏览器现状 国内的UC和QQ 百度等手机浏览器都是根据Webkit修改过来的内核,国内目前尚无自主研发的内核,就像国内的手机系统基本上都是局域安卓修改开发的一样. 意思就是:兼容移动端主流浏览器 处理Webkit内核浏览器即可. 1.2 手机屏幕的现状 移动端设备屏幕尺寸非常多,碎片化严重 Android设备有多种分辨率480*480 480*854 540*960 720*1280 等等 近年来iPhone的碎片化也严重了 其设备的主要分辨率有 640*960 640*

布局的几种方式(静态布局、自适应布局、流式布局、响应式布局、弹性布局)

一.静态布局(static layout) 即传统Web设计,网页上的所有元素的尺寸一律使用px作为单位. 1.布局特点 不管浏览器尺寸具体是多少,网页布局始终按照最初写代码时的布局来显示.常规的pc的网站都是静态(定宽度)布局的,也就是设置了min-width,这样的话,如果小于这个宽度就会出现滚动条,如果大于这个宽度则内容居中外加背景,这种设计常见于pc端. 2.设计方法 PC:居中布局,所有样式使用绝对宽度/高度(px),设计一个Layout,在屏幕宽高有调整时,使用横向和竖向的滚动条来查

流式布局&amp;固定宽度&amp;响应式&amp;rem

我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局.限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法. 1.流式布局: 例如流式布局的解决方案有不少弊端,它虽然可以让各种屏幕都适配,但是显示的效果极其的不好,因为只有几个尺寸的手机能够完美的显示出视觉设计师和交互最想要的效果. 他们在页面布局的时候都是通过百分比来定义宽度,但是高度大都是用px来固定住,所以在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但

关于静态布局、自适应布局、流式布局、响应式布局、弹性布局的一些概念

一.静态布局(Static Layout)即传统Web设计,网页上的所有元素的尺寸一律使用px作为单位. 1.布局特点:不管浏览器尺寸具体是多少,网页布局始终按照最初写代码时的布局来显示.常规的pc的网站都是静态(定宽度)布局的,也就是设置了min-width,这样的话,如果小于这个宽度就会出现滚动条,如果大于这个宽度则内容居中外加背景,这种设计常见与pc端.2.设计方法: PC:居中布局,所有样式使用绝对宽度/高度(px),设计一个Layout,在屏幕宽高有调整时,使用横向和竖向的滚动条来查阅

页面布局的几种方式(静态化布局,流式布局,自适应布局,响应式布局,弹性布局)

一.静态布局(static layout) 即传统Web设计,网页上的所有元素的尺寸一律使用px作为单位. 1.布局特点 不管浏览器尺寸具体是多少,网页布局始终按照最初写代码时的布局来显示.常规的pc的网站都是静态(定宽度)布局的,也就是设置了min-width,这样的话,如果小于这个宽度就会出现滚动条,如果大于这个宽度则内容居中外加背景,这种设计常见于pc端. https://developers.google.com/search/mobile-sites/mobile-seo/respon

瀑布流式布局

今天终于搞懂了瀑布流式布局,哈哈,总结下 瀑布流式布局分为两种类型:1.每一列都限定宽度不限定高度的布局(使用浮动)2.宽度不是写死的,是根据页面的放大缩小变化的(定位布局) 瀑布流式布局的重点是:每个新加载的模块都应该显示在原有模块高度最小的下方 注意事项: 图片:接收到的数据在插入到文档的过程中,可能会因为图片的加载速度影响Li的最小高度,可以等图片加载完触发某个事件,再继续加载图片(还未研究出):可以设置图片的相对宽高; 什么时候鼠标滚动的时候继续加载数据:当最小高度的模块显示在文档可视区

Android流式布局实现

查看我的全部开源项目[开源实验室] 欢迎加入我的QQ群:[201055521],本博客客户端下载[请点击] 摘要 新项目用到了一种全新布局----Android标签流式布局的功能,正好一直说给大家讲自定义控件的实现,今天就为大家讲一种android流式布局的实现. 本文原创,转载请注明地址:http://blog.kymjs.com/ 正文 在日常的app使用中,我们会在android 的app中看见热门标签等自动换行的流式布局,今天,我们就来看看如何自定义一个类似热门标签那样的流式布局吧(源码

(html+css)_移动端适配方案一(流式布局)

一.前言 二.主要内容 1.移动端面对的问题:因为手机屏幕和尺寸不一样,当我们用不同手机设备浏览的时候为了提高用户体验必须要做移动端适配 2.解决方案一: 流式布局 + viewport视口进行设置 流式布局:就是百分比布局,非固定像素,内容向两侧填充,理解成流动的布局,称为流式布局*/ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <

flutter wrap 流式布局

热门商品代码: import 'package:flutter/material.dart'; import 'package:flutter_project/service/service_method.dart'; import 'dart:convert'; import 'package:flutter_screenutil/flutter_screenutil.dart';//使用json.decode class HotGoods extends StatefulWidget { H