SingleChildRenderObjectWidget使用和说明:
- 可以放入一个child节点
- Widget在初次attach时createRenderObject
- Widget在更新时,触发自己的重建和RenderObject的update操作,Widget需要把自身的更改准确的传递给RenderObject.而RenderObject需要吸收变更内容,根据情况markNeedsPaint
- child主要是element操作(The child is optional.)
- mount和update的时候,element都会带一带child这个小老弟.同时要求本Widget的RenderObject需要With RenderObjectWithChildMixin(例如RenderProxyBox),让child有地方呆.
class MyRenderPhysicalShapeDemo extends StatefulWidget {
@override
MyRenderPhysicalShapeState createState() {
return MyRenderPhysicalShapeState();
}
}
class MyRenderPhysicalShapeState extends State<MyRenderPhysicalShapeDemo> {
double _elevation = 0.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('MyRenderPhysicalShapeDemo')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Slider(
value: _elevation,
onChanged: (value) => setState(() => _elevation = value),
),
MyPhysicalShape(
elevation: _elevation,
child: Container(
width: 50,
height: 50,
),
)
]));
}
}
class MyPhysicalShape extends SingleChildRenderObjectWidget {
final _elevation;
MyPhysicalShape({double elevation, Widget child})
: this._elevation = elevation,
super(child: child);
@override
RenderPhysicalShape createRenderObject(BuildContext context) {
return RenderPhysicalShape(
clipBehavior: Clip.none,
color: Color(0x61000000),
clipper: ShapeBorderClipper(
shape: CircleBorder(),
textDirection: Directionality.of(context),
),
shadowColor: Colors.black,
elevation: _elevation,
);
}
@override
void updateRenderObject(BuildContext context, RenderPhysicalShape renderObject) {
renderObject
..elevation = _elevation;
}
}
LeafRenderObjectWidget使用和说明: 这里比这SingleChildRenderObjectWidget少了child,其余相同.
class MyRenderBoxWidget extends LeafRenderObjectWidget {
final _elevation;
MyRenderBoxWidget({double elevation})
: this._elevation = elevation,
super();
@override
MyRenderBox createRenderObject(BuildContext context) {
return MyRenderBox(
elevation: _elevation,
);
}
@override
void updateRenderObject(BuildContext context, MyRenderBox renderObject) {
renderObject
..elevation = _elevation;
}
}
class MyRenderBox extends RenderBox {
MyRenderBox({
double elevation = 0.0,
}) : _elevation = elevation,
super();
@override
PhysicalModelLayer get layer => super.layer;
@override
Path get _defaultClip => Path()..addRect(Offset.zero & size);
@override
void performLayout() {
size = Size(100, 100);
}
@override
void paint(PaintingContext context, Offset offset) {
final Rect offsetBounds = offset & size;
final Path offsetPath = _defaultClip.shift(offset);
layer ??= PhysicalModelLayer();
layer
..clipPath = offsetPath
..clipBehavior = Clip.none
..elevation = elevation
..color = Color(0x61000000)
..shadowColor = Colors.black;
context.pushLayer(layer, super.paint, offset, childPaintBounds: offsetBounds);
}
double get elevation => _elevation;
double _elevation;
set elevation(double value) {
if (elevation == value)
return;
_elevation = value;
markNeedsPaint();
}
}
// addToScene 将内容传递给ui.SceneBuilder
class MyLayer extends ContainerLayer{
Path get clipPath => _clipPath;
Path _clipPath;
set clipPath(Path value) {
if (value != _clipPath) {
_clipPath = value;
markNeedsAddToScene();
}
}
/// {@macro flutter.widgets.Clip}
Clip get clipBehavior => _clipBehavior;
Clip _clipBehavior;
set clipBehavior(Clip value) {
assert(value != null);
if (value != _clipBehavior) {
_clipBehavior = value;
markNeedsAddToScene();
}
}
double get elevation => _elevation;
double _elevation;
set elevation(double value) {
if (value != _elevation) {
_elevation = value;
markNeedsAddToScene();
}
}
Color get color => _color;
Color _color;
set color(Color value) {
if (value != _color) {
_color = value;
markNeedsAddToScene();
}
}
/// The shadow color.
Color get shadowColor => _shadowColor;
Color _shadowColor;
set shadowColor(Color value) {
if (value != _shadowColor) {
_shadowColor = value;
markNeedsAddToScene();
}
}
@protected
ui.EngineLayer get engineLayer => _engineLayer;
@protected
set engineLayer(ui.EngineLayer value) {
super.engineLayer = value;
_engineLayer = value;
if (!alwaysNeedsAddToScene) {
if (parent != null && !parent.alwaysNeedsAddToScene) {
parent.markNeedsAddToScene();
}
}
}
ui.EngineLayer _engineLayer;
@override
void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
engineLayer = builder.pushPhysicalShape(
path: layerOffset == Offset.zero ? clipPath : clipPath.shift(layerOffset),
elevation: elevation,
color: color,
shadowColor: shadowColor,
clipBehavior: clipBehavior,
oldLayer: _engineLayer,
);
}
// 点击事件
@override
S find<S>(Offset regionOffset) {
return null;
}
// 点击事件
@override
Iterable<S> findAll<S>(Offset regionOffset) {
return null;
}
}