写点什么

Agora Flutter SDK:一套代码,实现双端通话(二)

  • 2019-11-30
  • 本文字数:2586 字

    阅读完需:约 8 分钟

Agora Flutter SDK:一套代码,实现双端通话(二)

绿色部分为我们定义的 Stingy,红色小方块为 Stingy 的 child ,这里是一个 Container


代码中的输入如下 (iphone 6 尺寸):


flutter: constraints: BoxConstraints(100.0<=w<=375.0, 100.0<=h<=300.0)flutter: childParentData: offset=Offset(275.0, 200.0)flutter: size: Size(375.0, 300.0)
复制代码


上述我们自定义 RenderBox 的 performLayout() 中做的事情可大概分为如下三个步骤:


  • 使用 child.layout(…) 来布局 child,这里是为 child 根据 parent 传递过来的约束选择一个大小

  • child.parentData.offset , 这是在为 child 如何摆放设置一个偏移量

  • 设置当前 widget 的 size


在我们的例子中,Stingy 的 child 是一个 Container,并且 Container 没有 child,因此他会使用 child.layout(…) 中设置的最大约束。通常,每个 widget 都会以不同的方式来处理提供给他的约束。如果我们使用 RaiseButton 替换 Container:


Stingy(    child: RaisedButton(      child: Text('Button'),    onPressed: (){}  )  )
复制代码


效果如下:



可以看到,RaisedButton 的 width 使用了 parent 给他传递的约束值 100,但是高度很明显没有 100,RaisedButton 的高度默认为 48 ,由此可见 RaisedButton 内部对 parent 传递过来的约束做了一些处理。


我们上面的 Stingy 继承的是 SingleChildRenderObjectWidget,也就是只能有一个 child。那如果有多个 child 怎么办,不用担心,这里还有一个 MultiChildRenderObjectWidget,而这个类有一个子类叫做 CustomMultiChildLayout,我们直接用这个子类就好。


先来看看 CustomMultiChildLayout 的构造方法如下:


/// The [delegate] argument must not be null.
CustomMultiChildLayout({ Key key, @required this.delegate, List<Widget> children = const <Widget>[],})
复制代码


  • key:widget 的一个标记,可以起到标识符的作用

  • delegate:这个特别重要,注释上明确指出这个参数一定不能为空,我们在下会说

  • children:这个就很好理解了,他是一个 widget 数组,也就是我们们需要渲染的 widget


上面的 delegate 参数类型如下:


  /// The delegate that controls the layout of the children.  final MultiChildLayoutDelegate delegate;
复制代码


可以看出 delegate 的类型为 MultiChildLayoutDelegate,并且注释也说明了它的作用:控制 children 的布局。也就是说,我们的 CustomMultiChildLayout 里面要怎么布局,完全取决于我们自定义的 MultiChildLayoutDelegate 里面的实现。所以 MultiChildLayoutDelegate 中也会有类似的 performLayout(…) 方法。


另外,CustomMultiChildLayout 中的每个 child 必须使用 LayoutId 包裹,注释如下:


/// Each child must be wrapped in a [LayoutId] widget to identify the widget for  /// the delegate.
复制代码


LayoutId 的构造方法如下:


  /// Marks a child with a layout identifier.  /// Both the child and the id arguments must not be null.  LayoutId({    Key key,    @required this.id,        @required Widget child  })
复制代码


注释的大概意思说的是:使用一个布局标识来标识一个 child;参数 child 和 参数 id 不定不能为空。 我们在布局 child 的时候会根据 child 的 id 来布局。


下面我们来使用 CustomMultiChildLayout 实现一个用于展示热门标签的效果:


Container(   child: CustomMultiChildLayout(     delegate: _LabelDelegate(itemCount: items.length, childId: childId),     children: items,   ), )
复制代码


我们的 _LabelDelegate 里面接受两个参数,一个为 itemCount,还有是 childId。


_LabelDelegate 代码如下:


class _LabelDelegate extends MultiChildLayoutDelegate {  final int itemCount;  final String childId;    // x 方向上的偏移量  double dx = 0.0;    // y 方向上的偏移量  double dy = 0.0;
_LabelDelegate({@required this.itemCount, @required this.childId}); @override void performLayout(Size size) { // 获取父控件的 width double parentWidth = size.width; for (int i = 0; i < itemCount; i++) { // 获取子控件的 id String id = '${this.childId}$i'; // 验证该 childId 是否对应一个 非空的 child if (hasChild(id)) { // layout child 并获取该 child 的 size Size childSize = layoutChild(id, BoxConstraints.loose(size)); // 换行条件判断 if (parentWidth - dx < childSize.width) { dx = 0; dy += childSize.height; } // 根据 Offset 来放置 child positionChild(id, Offset(dx, dy)); dx += childSize.width; } } } /// 该方法用来判断重新 layout 的条件 @override bool shouldRelayout(_LabelDelegate oldDelegate) { return oldDelegate.itemCount != this.itemCount; }}
复制代码


在 _LabelDelegate 中,重写了 performLayout(…) 方法。方法中有一个参数 size,这个 size 表示的是当前 widget 的 parent 的 size,在我们这个例子中也就表示 Container 的 size。我们可以看看 performLayout(…)方法的注释:


  /// Override this method to lay out and position all children given this  /// widget's size.  ///  /// This method must call [layoutChild] for each child. It should also specify  /// the final position of each child with [positionChild].  void performLayout(Size size);
复制代码


还有一个是 hasChild(…) 方法,这个方法接受一个 childId,childId 是由我们自己规定的,这个方法的作用是判断当前的 childId 是否对应着一个非空的 child。


满足 hasChild(…) 之后,接着就是 layoutChild(…) 来布局 child , 这个方法中我们会传递两个参数,一个是 childId,另外一个是 child 的约束(Constraints),这个方法返回的是当前这个 child 的 Size。


布局完成之后,就是如何摆放的问题了,也就是上述代码中的 positionChild(…) 了,此方法接受一个 childId 和 一个当前 child 对应的 Offset,parent 会根据这个 Offset 来放置当前的 child。


最后我们重写了 shouldRelayout(…) 方法用于判断重新 Layout 的条件。


完整源码在文章末尾给出。


效果如下:


2 Flutter 和 Native 的交互

我们这里说的 Native 指的是 Android 平台。


2019-11-30 15:04871

评论

发布
暂无评论
发现更多内容

ONE 2.0应用场景解读 | 如何通过时序拓扑直观还原故障传导链路?

博睿数据

可观测性 应用场景 智能运维 博睿数据 ONE平台

10分钟为你全面解答HDFS的SecondaryNamenode的作用

好程序员IT教育

大数据 hdfs

MatrixOne从入门到实战04——MatrixOne的连接和建表

MatrixOrigin

数据库 分布式 MatrixOrigin MatrixOne

5步法助力自动化转型

FunTester

关于平台工程的开发者工具链,你还想加点啥?

阿里巴巴云原生

阿里云 微服务 云原生 EDAS

阿里 CTO 程立:Severless 化正加速重塑阿里应用架构和研发模式

阿里巴巴云原生

阿里云 Serverless 云原生

分布式存储之 etcd 的集群管理

焱融科技

云计算 分布式系统 etcd 高性能 分布式存储

Chrome 103支持使用本地字体,纯前端导出PDF优化

葡萄城技术团队

chrome 前端 HTTP PDF

低代码开发是未来软件开发的主流模式

元年技术洞察

低代码 方舟PaaS

帮助中心:培养客户自助服务意识的实用工具

Baklib

Zebec流支付生态,开启多链布局的“两手准备”

鳄鱼视界

从手动测试到自动测试,企业该如何选择?

飞算JavaAI开发助手

折叠屏“世界杯”开哨,荣耀Magic Vs踢出关键一球

脑极体

年终最重磅!云原生实时数仓 SelectDB 首次产品发布等你来约!

SelectDB

数据库 云计算 大数据 实时计算

DevData Talks | 知乎艾辉:从工具建设到运营,千人团队研发提效最佳实践

思码逸研发效能

研发管理 研发效能

专利解析|多维建模结合AI识别商品特征的方法

元年技术洞察

AI 数字化转型

开源让这位00后逆袭成为各类大奖收割者

OpenI启智社区

开源 OpenI启智社区 免费算力

游戏品类加速回暖,文娱内容持续火热——2022年IAA行业品类发展洞察系列报告·第三期

易观分析

游戏 报告 文娱

MatrixOne从入门到实践05——数据类型介绍

MatrixOrigin

数据库 分布式 MatrixOrigin MatrixOne

如何用JavaScripte和HTML 实现一整套的考试答题卡和成绩表

葡萄城技术团队

Serverless Devs 社区联合信通院邀请您参加 2022 中国 Serverless 用户调查

阿里巴巴云原生

阿里云 Serverless 云原生

阿里云云原生加速器成员企业袋鼠云创始人陈吉平:深耕国产自研数字化技术与服务,持续为客户创造价值

阿里巴巴云原生

阿里云 云原生

第三章 TCP/IP ip地址概念与应用

我叫于豆豆吖.

11月月更

三分建设,七分运营|用现代化安全运营应对数据安全风险

爱科技的水月

如何通过Java 合并和取消合并 Excel 单元格

在下毛毛雨

Java Excel 合并单元格

Hire Remote Developers

Mahipal_Nehra

Java angular blockchain React app development

数据监控预警系统,实现不同端信息推送

葡萄城技术团队

前端 数据可视化

《数据》杂志 | 浅析《网络安全法》修改对数据合规与隐私计算的影响

洞见科技

容器服务 ACK 结合 MSE Ingress,让集群入口流量管理更丰富、更容易

阿里巴巴云原生

阿里云 云原生 容器服务

Amazon Braket 与量子计算

亚马逊云科技 (Amazon Web Services)

量子计算 Hero 专栏 Amazon Braket

Stack Memory vs Heap Memory in Java

Mahipal_Nehra

Java heap memory Stack memory Java development

Agora Flutter SDK:一套代码,实现双端通话(二)_文化 & 方法_声网_InfoQ精选文章