对于绘制child的顺序,则是第一个child被绘制在最底端,后面的依次在前一个child的上面,类似于web中的z-index。如果想调整显示的顺序,则可以通过摆放child的顺序来进行。
1.3 继承关系
Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > MultiChildRenderObjectWidget > Stack
1.4 示例代码
Stack(
alignment: const Alignment(0.6, 0.6),
children: [
CircleAvatar(
backgroundImage: AssetImage(‘images/pic.jpg’),
radius: 100.0,
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text(
‘Mia B’,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
);
示例代码我就直接用的Building Layouts in Flutter中的例子,效果如下
1.5 源码解析
构造函数如下:
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List children = const [],
})
1.5.1 属性解析
alignment:对齐方式,默认是左上角(topStart)。
textDirection:文本的方向,绝大部分不需要处理。
fit:定义如何设置non-positioned节点尺寸,默认为loose。
其中StackFit有如下几种:
- loose:子节点宽松的取值,可以从min到max的尺寸;
- expand:子节点尽可能的占用空间,取max尺寸;
- passthrough:不改变子节点的约束条件。
overflow:超过的部分是否裁剪掉(clipped)。
1.5.2 源码
Stack的布局代码有些长,在此分段进行讲解。
-
- 如果不包含子节点,则尺寸尽可能大。
if (childCount == 0) {
size = constraints.biggest;
return;
}
- 2.根据fit属性,设置non-positioned子节点约束条件。
switch (fit) {
case StackFit.loose:
nonPositionedConstraints = constraints.loosen();
break;
case StackFit.expand:
nonPositionedConstraints = new BoxConstraints.tight(constraints.biggest);
break;
case StackFit.passthrough:
nonPositionedConstraints = constraints;
break;
}
- 3.对non-positioned子节点进行布局。
RenderBox child = firstChild;
while (child != null) {
final StackParentData childParentData = child.parentData;
if (!childParentData.isPositioned) {
hasNonPositionedChildren = true;
child.layout(nonPositionedConstraints, parentUsesSize: true);
final Size childSize = child.size;
width = math.max(width, childSize.width);
height = math.max(height, childSize.height);
}
child = childParentData.nextSibling;
}
- 4.根据是否包含positioned子节点,对stack进行尺寸调整。
if (hasNonPositionedChildren) {
size = new Size(width, height);
} else {
size = constraints.biggest;
}
- 5.最后对子节点位置的调整,这个调整过程中,则根据alignment、positioned节点的绝对位置等信息,对子节点进行布局。
第一步是根据positioned的绝对位置,计算出约束条件后进行布局。
if (childParentData.left != null && childParentData.right != null)
childConstraints = childConstraints.tighten(width: size.width - childParentData.right - childParentData.left);
else if (childParentData.width != null)
childConstraints = childConstraints.tighten(width: childParentData.width);
if (childParentData.top != null && childParentData.bottom != null)
childConstraints = childConstraints.tighten(height: size.height - childParentData.bottom - childParentData.top);
else if (childParentData.height != null)
childConstraints = childConstraints.tighten(height: childParentData.height);
child.layout(childConstraints, parentUsesSize: true);
第二步则是位置的调整,其中坐标的计算如下:
double x;
if (childParentData.left != null) {
x = childParentData.left;
} else if (childParentData.right != null) {
x = size.width - childParentData.right - child.size.width;
} else {
x = _resolvedAlignment.alongOffset(size - child.size).dx;
}
if (x < 0.0 || x + child.size.width > size.width)
_hasVisualOverflow = true;
double y;
if (childParentData.top != null) {
y = childParentData.top;
} else if (childParentData.bottom != null) {
y = size.height - childParentData.bottom - child.size.height;
} else {
y = _resolvedAlignment.alongOffset(size - child.size).dy;
}
if (y < 0.0 || y + child.size.height > size.height)
_hasVisualOverflow = true;
childParentData.offset = new Offset(x, y);
1.6 使用场景
Stack的场景还是比较多的,对于需要叠加显示的布局,一般都可以使用Stack。有些场景下,也可以被其他控件替代,我们应该选择开销较小的控件去实现。
2. IndexedStack
A Stack that shows a single child from a list of children.
2.1 简介
IndexedStack继承自Stack,它的作用是显示第index个child,其他child都是不可见的。所以IndexedStack的尺寸永远是跟最大的子节点尺寸一致。
2.2 例子
在此还是将Stack的例子稍加改造,将index设置为1,也就是显示含文本的Container的节点。
Container(
color: Colors.yellow,
child: IndexedStack(
index: 1,
alignment: const Alignment(0.6, 0.6),
children: [
CircleAvatar(
backgroundImage: AssetImage(‘images/pic.jpg’),
radius: 100.0,
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text(
‘Mia B’,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
),
)
2.3 源码解析
其绘制代码很简单,因为继承自Stack,布局方面表现基本一致,不同之处在于其绘制的时候,只是将第Index个child进行了绘制。
@override
void paintStack(PaintingContext context, Offset offset) {
if (firstChild == null || index == null)
return;
final RenderBox child = _childAtIndex();
final StackParentData childParentData = child.parentData;
context.paintChild(child, childParentData.offset + offset);
}
2.4 使用场景
如果需要展示一堆控件中的一个,可以使用IndexedStack。有一定的使用场景,但是也有控件可以实现其功能,只不过操作起来可能会复杂一些。
3. GridView
A scrollable, 2D array of widgets.
3.1 简介
GridView在移动端上非常的常见,就是一个滚动的多列列表,实际的使用场景也非常的多。
3.2 布局行为
GridView的布局行为不复杂,本身是尽量占满空间区域,布局行为上完全继承自ScrollView。
3.3 继承关系
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
文末
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!