缘起缘灭 之Builder的使用 获取child的位置 大小信息

85 阅读1分钟

前置知识点:ctx.findRenderObject()找的是离ctx最近的类型为RenderObjectElement 的child的renderObject。

RenderObject? get renderObject {
  Element? current = this;
  while (current != null) {
    if (current._lifecycleState == _ElementLifecycle.defunct) {
      break;
    } else if (current is RenderObjectElement) {
      return current.renderObject;
    } else {
      Element? next;
      current.visitChildren((Element child) {
        assert(next == null);  // This verifies that there's only one child.
        next = child;
      });
      current = next;
    }
  }
  return null;
}

所以可以直接通过Builder获取BuilderContext,来获取child的位置大小信息


import 'package:flutter/material.dart';

class BuilderWidgetPage extends StatefulWidget {

  const BuilderWidgetPage({super.key});


  @override
  State<StatefulWidget> createState() => _BuilderWidgetPageState();

}

class _BuilderWidgetPageState extends State<BuilderWidgetPage> {

  late BuildContext ctx;
  Offset offset = const Offset(0, 0);
  Size size = Size(0, 0);
  @override
  Widget build(BuildContext context) {

    return GestureDetector(
      onTap: (){
        //
        var renderBox =  ctx.findRenderObject() as RenderBox;
        offset = renderBox.localToGlobal(Offset.zero);
        size = renderBox.size;
        setState(() {

        });
      },
      child: Container(
        color: Colors.red,
        alignment: Alignment.center,
        child: Builder(
          builder: (ctx){
            this.ctx = ctx;
            return Container(
              color: Colors.yellow,
              width: 100,
              height: 100,
              alignment: Alignment.center,
              child: Text("${offset.dx}\n${offset.dy}\n${size.width}\n${size.height}",style: TextStyle(fontSize: 12),),
            );
          },
        ),
      ),
    );
  }
}