① relayoutBoundary
重布局边界。该参数用于表示子节点布局变化是否影响父节点,如果为true,当子节点布局发生变化时父节点都会标记为需要重新布局,如果为false,则子节点布局发生变化后不会影响父节点。
void layout(Constraints constraints, { bool parentUsesSize = false }) {
...
RenderObject relayoutBoundary;
if (!parentUsesSize || sizedByParent || constraints.isTight
|| parent is! RenderObject) {
relayoutBoundary = this;
} else {
final RenderObject parent = this.parent;
relayoutBoundary = parent._relayoutBoundary;
}
...
if (sizedByParent) {
performResize();
}
performLayout();
...
}
② performResize()
当 sizedByParent 为true 时,节点的大小仅通过 parent 传给它的 constraints 就可以确定了,即该节点的大小与它自身的属性和其子节点无关,此时其大小在 performResize() 中就确定了,performLayout() 不能用于改变组件大小。
class _RenderCircleBox extends RenderProxyBox {
_RenderCircleBox();
@override
bool get sizedByParent => true;
@override
void performResize() {
super.performResize();
size = constraints.constrain(Size(constraints.maxWidth, 100));
}
@override
void performLayout() {
}
}
③ RepaintBoundary
独立绘制边界
1)如果没有该边界,别的组件重绘(如执行动画、CustomPainter 中 shouldRepaint 返回 true 等)会导致整个 Layer 重绘,继而导致包含在同一个 Layer 的当前组件重绘;反之,当前组件重绘也会影响别的组件(如果有边界,在绘制时仅会重绘自身而无需重绘它的 parent)。
示例:共享 Layer 导致的重绘
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
print('home dd');
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircleBox(),
SquareBox(),
],
)),
);
}
}
class CircleBox extends LeafRenderObjectWidget {
const CircleBox({super.key});
@override
RenderObject createRenderObject(BuildContext context) {
return _RenderCircleBox();
}
}
class _RenderCircleBox extends RenderProxyBox {
_RenderCircleBox();
@override
void performLayout() {
super.performLayout();
size = constraints.constrain(Size(100, 100));
}
@override
void paint(PaintingContext context, Offset offset) {
print('circle painting...');
context.canvas.drawCircle(offset.translate(50, 50), size.width / 2, Paint());
}
@override
bool hitTest(BoxHitTestResult result, {required Offset position}) {
return false;
}
// 当 isRepaintBoundary 返回 false,SquareBox 点击时触发的动画导致 Layer 重绘,继而导致 CircleBox 重绘。
@override
bool get isRepaintBoundary => false;
}
class SquareBox extends StatefulWidget {
const SquareBox({Key? key}) : super(key: key);
@override
State<SquareBox> createState() => _SquareBoxState();
}
class _SquareBoxState extends State<SquareBox> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print('square build');
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_controller.forward(from: 0);
},
child: RotationTransition(
turns: Tween(begin: 0.0, end: 0.5).animate(_controller),
child: Container(
color: Colors.green,
height: 200,
width: 200,
),
),
);
}
}
注:
setState 执行的是 markNeedsBuild,会导致 widget 重建(调用 Element 的 rebuild 方法 ),但不一定会导致节点重绘(调用 RenderObject 的 markNeedsPaint 方法)。参考 setState 流程
有几种情况会导致组件重绘:
- 当 widget 重建导致布局信息变化影响子节点布局时,会导致子节点重绘
- 重建时子节点执行 updateRenderObject 方法,如果 renderObject 属性变化,则通常会调用 markNeedsPaint() 重绘
- 对于子节点是 CustomPaint,执行 updateRenderObject 方法会调用 set painter 属性方法,该方法执行时判断 CustomPainter 组件的 shouldRepaint 方法是否返回 true,若返回 true 则会调用 markNeedsPaint() 重绘。
2)设置边界的情况下,自定义 RenderBox 组件,默认布局,在绘制时 offset 是相对当前 Layer(可以理解为画布)进行偏移。
class RenderRepaintBoundary extends RenderProxyBox {
/// Creates a repaint boundary around [child].
RenderRepaintBoundary({ RenderBox child }) : super(child);
@override
void paint(PaintingContext context, Offset offset) {
// 参数列表中的 offset 是相对当前 layer 的偏移量。同时 drawCircle 的起始偏移也是相对于当前 layer 进行偏移。
// 如果 isRepaintBoundary 返回 true,节点自身就是 layer,那么参数列表中的 offset 等于零,
// drawCircle 则是相当于当前节点自身位置进行绘制。
context.canvas.drawCircle(Offset(10, 10), size.width / 2, Paint());
}
// 也可直接用 RepaintBoundary 对当前组件进行包装
@override
bool get isRepaintBoundary => true;
}
标签:RenderObject,void,节点,extends,override,原理,flutter,super,重绘
From: https://www.cnblogs.com/lemos/p/17089087.html