Flutter 如何根据其子项定位复合TransformFollower';s码?

Flutter 如何根据其子项定位复合TransformFollower';s码?,flutter,Flutter,我正在使用CompositedTransformTarget和CompositedTransformFollower显示一个OverlayEntry。如何相对于复合传输目标定位复合传输目标下方,即如何将其底部与目标顶部中心对齐,以便在目标上方水平居中显示,同时保持交互性(即对子对象进行命中测试应能正常工作) 我试图计算偏移量以提供给复合传输功率,但我无法进行正确的计算,因为当时我没有孩子的大小 示例代码: 导入“包装:颤振/材料.省道”; void main(){ runApp(MyApp())

我正在使用
CompositedTransformTarget
CompositedTransformFollower
显示一个
OverlayEntry
。如何相对于
复合传输目标定位
复合传输目标下方
,即如何将其底部与目标顶部中心对齐,以便在目标上方水平居中显示,同时保持交互性(即对子对象进行命中测试应能正常工作)

我试图计算
偏移量
以提供给
复合传输功率
,但我无法进行正确的计算,因为当时我没有孩子的大小

示例代码:

导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
主题:主题数据(亮度:亮度。灯光),
家:脚手架(
appBar:appBar(标题:Text('test')),
主体:居中(子项:重叠按钮()),
),
);
}
}
类OverlayButton扩展StatefulWidget{
@凌驾
_OverlayButtonState createState()=>_OverlayButtonState();
}
类覆盖按钮状态扩展状态{
过度进入(OverlayEntry);;
最终层链接_LayerLink=LayerLink();
bool _=false;
@凌驾
无效处置(){
super.dispose();
如果(如图所示){
_hideOverlay();
}
}
void_showOverlay(){
如果(如图所示)返回;
_overlayEntry=_createOverlayEntry();
覆盖.of(上下文).insert(_overlayEntry);
_所示为真;
}
void _hideOverlay(){
_结果显示为假;
_覆盖入口。移除();
}
@凌驾
小部件构建(构建上下文){
返回复合传输目标(
链接:_layerLink,
子项:RaisedButton(子项:文本(‘打开覆盖’),按下时:_showOverlay),
);
}
OverlayEntry_createOverlayEntry(){
RenderBox RenderBox=context.findenderobject();
var anchorSize=renderBox.size;
返回覆盖入口(生成器:(上下文){
//TODO:动态使用正确的子项宽度/高度
//将我们正确定位在顶部+以锚为中心
var-childWidth=200.0;
var-childHeight=40.0;
变量childOffset=
偏移量(-(childWidth-anchorSize.width)/2,-(childHeight));
返回行(
儿童:[
复合传输功率(
链接:_layerLink,
偏移量:childOffset,
孩子:升起按钮(
子项:文本('close'),
按下按钮:_hideOverlay,
),
),
],
);
});
}
}

一般回答:

看起来我们想知道孩子的确切大小,然后再决定把孩子放在哪里。有一个用于此目的的小部件,名为
CustomSingleChildLayout
。此外,如果需要布局多个子项,则应查看稍微复杂一点的版本,
CustomMultiChildLayout

对于这种情况:

首先,您需要在正在构建的
OverlayEntry
中插入一个
CustomSingleChildLayout
,例如,我在这里添加了两行:

  OverlayEntry _createOverlayEntry() {
    RenderBox renderBox = context.findRenderObject();
    var anchorSize = renderBox.size;
    return OverlayEntry(builder: (context) {
      return CompositedTransformFollower(
        link: _layerLink,
        child: CustomSingleChildLayout(     // # Added Line 1 #
          delegate: MyDelegate(anchorSize), // # Added Line 2 #
          child: RaisedButton(
            child: Text('close'),
            onPressed: _hideOverlay,
          ),
        ),
      );
    });
  }
然后,让我们创建一个处理业务逻辑的委托。请注意,我还创建了一个参数,用于接收“anchorSize”:

如您所见,在
getPositionForChild
方法中,我们能够收集计算偏移量所需的所有信息。计算之后,我们可以返回该偏移量,
CustomSingleChildLayout
将负责放置


为了扩展这个想法,你甚至可能不再需要
复合传输follow
,你只需要做一个全屏覆盖,然后用这种方式计算偏移量。

你必须用Follower小部件来实现这一点。我在这里做了一个
class MyDelegate extends SingleChildLayoutDelegate {
  final Size anchorSize;

  MyDelegate(this.anchorSize);

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    // we allow our child to be smaller than parent's constraint:
    return constraints.loosen();
  }

  @override
  Offset getPositionForChild(Size size, Size childSize) {
    print("my size: $size");
    print("childSize: $childSize");
    print("anchor size being passed in: $anchorSize}");
    // todo: where to position the child? perform calculation here:
    return Offset(anchorSize.width, childSize.height / 2);
  }

  @override
  bool shouldRelayout(_) => true;
}