Widget 配置信息
@immutable
abstract class Widget extends DiagnosticableTree {
/// Initializes [key] for subclasses.
const Widget({ this.key });
final Key? key;
@override
String toStringShort() {
final String type = objectRuntimeType(this, 'Widget');
return key == null ? type : '$type-$key';
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
}
@override
@nonVirtual
bool operator ==(Object other) => super == other;
@override
@nonVirtual
int get hashCode => super.hashCode;
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
static int _debugConcreteSubtype(Widget widget) {
return widget is StatefulWidget ? 1 :
widget is StatelessWidget ? 2 :
0;
}
}
abstract class RenderObjectWidget extends Widget {
const RenderObjectWidget({ Key? key }) : super(key: key);
@override
@factory
RenderObjectElement createElement();
@protected
@factory
RenderObject createRenderObject(BuildContext context);
@protected
void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
@protected
void didUnmountRenderObject(covariant RenderObject renderObject) { }
}
Widget子类
- RenderObjectWidget
- SingleChildRenderObjectWidget
- MultiChildRenderObjectWidget
- StatefulWidget
- StatelessWidget
- SingleChildWidget
- PreferredSizeWidget
- CustomMultiChildLayout
- CustomSingleChildLayout
RenderObject 最后干活的人
class ShadowBox extends SingleChildRenderObjectWidget {
final Widget? child;
final double? distance;
ShadowBox({this.child, this.distance = 20}) : super(child: child);
//运行时类型和key一样的话不会重新创建RenderObject
@override
RenderObject createRenderObject(BuildContext context) {
return RenderShadowBox2(distance);
}
//因为类型没有变RenderBox就会捡回去继续使用,但是你可以修改RenderBox的属性
@override
void updateRenderObject(
BuildContext context, covariant RenderShadowBox2 renderObject) {
renderObject.distance = distance;
}
}
///继承功能相似的RenderBox
class RenderShadowBox extends RenderBox with RenderObjectWithChildMixin {
double? distance;
RenderShadowBox(this.distance);
@override
void performLayout() {
//父组件使用子size 因为有些 父组件不需要使用子组件的size
child?.layout(constraints, parentUsesSize: true);
//child?.layout(BoxConstraints.tight(Size(50,50)));
//size = Size(300,300);
size = (child as RenderBox).size;
}
//无中生有
@override
void paint(PaintingContext context, Offset offset) {
context.paintChild(child!, offset);
var canvas = context.canvas;
// canvas.drawCircle(offset+Offset(50,50), 50, Paint()..color=Colors.white);
//建立新的图层
context.pushOpacity(offset, 127, (context, offset) {
context.paintChild(
child!, offset + Offset(distance ?? 20, distance ?? 20));
});
}
}
class RenderShadowBox2 extends RenderProxyBox with DebugOverflowIndicatorMixin {
double? distance;
RenderShadowBox2(this.distance);
//无中生有
@override
void paint(PaintingContext context, Offset offset) {
context.paintChild(child!, offset);
context.pushOpacity(offset, 127, (context, offset) {
context.paintChild(
child!, offset + Offset(distance ?? 20, distance ?? 20));
});
//开发者 自己画的
paintOverflowIndicator(
context,
offset,
//能画的区域
//Rect.fromLTWH(0, 0, size.width, size.height),
Offset.zero & size,
//子组件要画的区域
//Rect.fromLTWH(0, 0, 320, 300),
Offset.zero & child!.size,
);
}
}
///使用MyMultiChildLayoutDelegate
CustomMultiChildLayout(
delegate: MyMultiChildLayoutDelegate(),
children: [
LayoutId(
child: Container(
color: Colors.red,
),
id: "underline",
),
LayoutId(
child: Text("WSBT"),
id: "text",
),
],
)
class MyMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
late Size size1,size2,size3,size4,size5;
double top = 100;
@override
Size getSize(BoxConstraints constraints) {
// TODO: implement getSize
return Size(400,400);
}
@override
void performLayout(Size size) {
if (hasChild(1)) {
size1 = layoutChild(
1,
BoxConstraints(
minHeight: 50, maxHeight: 50, minWidth: 50, maxWidth: 50));
positionChild(1, Offset(0, top));
}
if (hasChild(2)) {
size2 = layoutChild(
2,
BoxConstraints.tight(Size(80,80)));
positionChild(2, Offset(size1.width, top+size1.height));
}
if (hasChild(3)) {
size3 = layoutChild(
3,
BoxConstraints.loose(size));
positionChild(3, Offset(size1.width+size2.width, top+size1.height+size2.height));
}
if (hasChild(4)) {
size4 = layoutChild(
4,
BoxConstraints.loose(size));
positionChild(4, Offset(0,0));
}
if (hasChild(5)) {
size5 = layoutChild(
5,
BoxConstraints.tight(
Size(
size4.width, 5)
));
positionChild(5, Offset(0,size4.height));
}
}
@override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
return true;
}
}
//使用
body: Container(
color: Colors.blue,
child: CustomMultiChildLayout(
delegate: MyMultiChildLayoutDelegate(),
children: [
LayoutId(id: 1, child: FlutterLogo()),
LayoutId(id: 2, child: FlutterLogo()),
LayoutId(id: 3, child: FlutterLogo(size: 100,)),
LayoutId(id: 4, child: Text("hello")),
LayoutId(id: 5, child: Container(color: Colors.red)),
],
),
),
另外一个干活的
class MyCustomPainter extends CustomPainter {
final List<Snowflake> _datas;
final whitePaint = Paint()..color = Colors.white;
MyCustomPainter(this._datas);
@override
void paint(Canvas canvas, Size size) {
//loge(size);
//canvas.drawCircle(Offset(size.width/2, size.height/2), 20, Paint());
canvas.drawCircle(size.center(Offset(0, 100)), 60, whitePaint);
canvas.drawOval(
Rect.fromCenter(
center: size.center(Offset(0, 280)), width: 200, height: 250),
whitePaint);
_datas.forEach((snowflake) {
canvas.drawCircle(
Offset(snowflake.x, snowflake.y), snowflake.radius, whitePaint);
});
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
RenderObject
RenderBox
Element 事比较多
- mount->widget.createRenderObject(this)
- update->widget.updateRenderObject(this, renderObject)
- updateChild->通过widget更改子
Element子类
- ComponentElement
1.1 不会直接创建RenderObject,但是会创建其他的element,让他们创建RenderObject
1.2 StatelessElement StatefulElement ProxyElement
- RenderObjectElement
2.1 会直接创建ReaderObject