flutter 布局原理,2024年最新熬夜整理小米HarmonyOS鸿蒙面试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新HarmonyOS鸿蒙全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img

img
img
htt

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注鸿蒙)
img

正文

}

if (decoration != null) {
current = DecoratedBox(decoration: decoration!, child: current);
}

if (foregroundDecoration != null) {
current = DecoratedBox(
decoration: foregroundDecoration!,
position: DecorationPosition.foreground,
child: current,
);
}

if (constraints != null) {
current = ConstrainedBox(constraints: constraints!, child: current);
}

if (margin != null) {
current = Padding(padding: margin!, child: current);
}

if (transform != null) {
current = Transform(transform: transform!, alignment: transformAlignment, child: current);
}

return current!;
}

组合类基本不参与ui的绘制,都是通过绘制类的组合来实现功能。

3、flutter布局约束

flutter中有两种布局约束BoxConstraints盒约束和SliverConstraints线性约束,如Align、Padding、ConstrainedBox使用的是盒约束。

BoxConstraints盒约束是指flutter框架在运行时遍历整个组件树,在这过程中 「向下传递约束,向上传递尺寸」,以此来确定每个组件的尺寸和大小。

BoxConstraints类由4个属性组成,最小宽度minWidth、最大宽度maxWidth、最小高度minHeight、最大高度maxHeight

BoxConstraints({
this.minWidth,
this.maxWidth,
this.minHeight,
this.maxHeight,
});

根据这4个属性的变化,可以分为“紧约束(tight)”、“松约束(loose)”、“无界约束”、“有界约束”。

紧约束:最小宽(高)度和最大宽(高)度值相等,此时它是一个固定宽高的约束。

BoxConstraints.tight(Size size)
minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;

松约束:最小宽(高)值为0,最大宽(高)大于0,此时它是一个约束范围。

BoxConstraints.loose(Size size)
minWidth = 0.0,
maxWidth = size.width,
minHeight = 0.0,
maxHeight = size.height;

无界约束:最小宽(高)和最大宽(高)值存在double.infinity(无限)。

BoxConstraints.expand({double? width, double? height})
minWidth = width ?? double.infinity,
maxWidth = width ?? double.infinity,
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;

有界约束:最小宽(高)和最大宽(高)值均为固定值。

BoxConstraints(100, 300, 100, 300)

4、Container布局行为解惑

了解了BoxConstraints布局约束,回到本文最开始的问题。

/// 例一
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: Colors.amber,
child: Container(width: 50, height: 50, color: Colors.red,),
);
}

例一中,两个固定宽高的Container,为什么子容器铺满了全屏?

根据BoxConstraints布局约束,遍历整个组件树,最开始的root是树的起点,它向下传递的是一个紧约束。因为是移动设备,root即是屏幕的大小,假设屏幕宽414、高896。于是整个布局约束如下:

这里有个问题,就是Container分明已经设置了固定宽高,为什么无效?

因为父级向下传递的约束,子组件必须严格遵守。这里Container容器设置的宽高超出了父级的约束范围,就会自动被忽略,采用符合约束的值。

例一两上Container都被铺满屏幕,而最底下的红色Container叠到了最上层,所以最终显示红色。

/// 例二
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: Colors.amber,
alignment: Alignment.center,
child: Container(width: 50, height: 50, color: Colors.red,),
);
}

例二也同样可以根据布局约束求证,如下图:

这里Container为什么是ConstrainedBoxAlign组件?前面说过Container是一个组合组件,它是由多个原子组件组成的。根据例二,它是由ConstrainedBox和Align嵌套而成。

Align提供给子组件的是一个松约束,所以容器自身设置50宽高值是在合理范围的,因此生效,屏幕上显示的就是50像素的红色方块。ConstrainedBox受到的是紧约束,所以自身的300宽高被忽略,显示的是铺满屏幕的黄色块。

/// 例三
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 300,
height: 300,
color: Colors.amber,
alignment: Alignment.center,
child: Container(width: 50, height: 50, color: Colors.red,),
),
);
}

例三中Scaffold向下传递的是一个松约束,所以黄色Container的宽高根据自身设置的300,在合理的范围内,有效。Container再向下传递的也是松约束,最终红色Container宽高为50。

这里还有个问题,怎么确定组件向下传递的是紧约束还是松约束?

这就涉及到组件的内部实现了,这里通过Align举个例。

Align是一个绘制组件,它能够进行界面的布局和绘制,这是因为Align的继承链为:

Align -> SingleChildRenderObjectWidget -> RenderObjectWidget

Align需要重写createRenderObject方法,返回RenderObject的实现,这里Align返回的是RenderPositionedBox,所以核心内容就在这个类中

class Align extends SingleChildRenderObjectWidget {
/// …
@override
RenderPositionedBox createRenderObject(BuildContext context) {
return RenderPositionedBox(
alignment: alignment,
widthFactor: widthFactor,
heightFactor: heightFactor,
textDirection: Directionality.maybeOf(context),
);
}
/// …
}

而RenderPositionedBox类中,重写performLayout方法,该方法用于根据自身约束条件,计算出子组件的布局,再根据子组件的尺寸设置自身的尺寸,形成一个至下而上,由上到下的闭环,最终实现界面的整个绘制。

RenderPositionedBox -> RenderAligningShiftedBox -> RenderShiftedBox -> RenderBox

class RenderPositionedBox extends RenderAligningShiftedBox {
/// …
@override
void performLayout() {
final BoxConstraints constraints = this.constraints; // 自身的约束大小
final bool shrinkWrapWidth = _widthFactor != null || constraints.maxWidth == double.infinity;
final bool shrinkWrapHeight = _heightFactor != null || constraints.maxHeight == double.infinity;
/// 存在子组件
if (child != null) {
/// 开始布局子组件
child!.layout(constraints.loosen(), parentUsesSize: true);
/// 根据子组件的尺寸设置自身尺寸
size = constraints.constrain(Size(
shrinkWrapWidth ? child!.size.width * (_widthFactor ?? 1.0) : double.infinity,
shrinkWrapHeight ? child!.size.height * (_heightFactor ?? 1.0) : double.infinity,
));
/// 计算子组件的位置
alignChild();
} else {
/// 不存在子组件
size = constraints.constrain(Size(
shrinkWrapWidth ? 0.0 : double.infinity,
shrinkWrapHeight ? 0.0 : double.infinity,
));
}
}
/// …
}

根据Align中performLayout方法的实现,可以确定该组件最终会给子组件传递一个怎么样的约束。

/// constraints.loosen提供的是一个松约束
child!.layout(constraints.loosen(), parentUsesSize: true);

/// loosen方法
BoxConstraints loosen() {
assert(debugAssertIsValid());
/// BoxConstraints({double minWidth = 0.0, double maxWidth = double.infinity, double minHeight = 0.0, double maxHeight = double.infinity})
return BoxConstraints(
maxWidth: maxWidth,
maxHeight: maxHeight,
);
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注鸿蒙)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

return BoxConstraints(
maxWidth: maxWidth,
maxHeight: maxHeight,
);
}

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注鸿蒙)
[外链图片转存中…(img-md8aLvMQ-1713124737693)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您介绍一些常见的Flutter面试题。以下是一些常见的Flutter面试题及其答案: 1. Flutter是什么?它有哪些特点? Flutter是一个跨平台的移动应用开发框架,由Google开发。它具有以下特点: - 快速开发:使用热重载功能可以快速进行开发和调试。 - 跨平台:可以在iOS和Android等多个平台上运行。 - 漂亮的UI:Flutter提供了丰富的UI组件,可以创建漂亮的用户界面。 - 高性能:Flutter使用自绘引擎,可以实现高性能的应用程序。 2. Flutter中的Widget是什么? 在Flutter中,一切都是Widget。Widget是Flutter应用程序的基本构建块,用于构建用户界面。Widget可以是一个简单的按钮或文本,也可以是一个复杂的布局。 3. 什么是StatefulWidget和StatelessWidget? StatefulWidget和StatelessWidget是Flutter中两种常见的Widget类型。 - StatefulWidget:具有可变状态的Widget,可以根据状态的变化重新构建UI。 - StatelessWidget:没有可变状态的Widget,一旦构建完成就不会再改变。 4. 什么是热重载(Hot Reload)? 热重载是Flutter的一个强大功能,它允许开发者在不重新启动应用程序的情况下快速查看代码更改后的效果。通过热重载,开发者可以实时地看到UI的变化,加快开发速度。 5. Flutter中的路由是什么? 在Flutter中,路由用于管理页面之间的导航。每个页面都有一个唯一的路由名称,可以通过路由名称来打开或关闭页面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值