0

如何获得拖动对象的左上角?

下面的代码可以直接在 web 中测试。它在渲染后打印尺寸和一些奇怪的(没用的?)翻译值。我想将矩形与网格对齐。

import 'package:flutter/material.dart';

List<DBTableView> tableViews = [];

void main() {
  tableViews = [
    DBTableView(
      table: DBTable()
        ..name = 'user'
        ..columns = ['id bigserial', 'name text']
        ..offset = const Offset(50, 50),
    ),
    DBTableView(
      table: DBTable()
        ..name = 'role'
        ..columns = ['id bigserial', 'role char(20)']
        ..offset = const Offset(100, 100),
    ),
  ];
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ER-Modeler',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('ER-Modeler')),
      body: GridPaper(
        interval: 50,
        child: DragTarget<DBTableView>(
          onAcceptWithDetails: (DragTargetDetails<DBTableView> details) =>
              _onDrop(details),
          onWillAccept: (_) => true,
          builder: (BuildContext ctx, List<Object?> candidateData,
                  List<dynamic> rejectedData) =>
              Stack(
            children: tableViews,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(
          () => tableViews.add(
            DBTableView(
                table: DBTable()
                  ..name = 'Table #$counter'
                  ..columns = ['id bigserial', 'name text']),
          ),
        ),
        tooltip: 'Add Table',
        child: const Icon(Icons.add),
      ),
    );
  }

  _onDrop(DragTargetDetails<DBTableView> details) {
    GlobalKey key = details.data.table.key;
    Size? size = key.currentContext?.size;
    if (size != null) {
      print('size = $size');
    }
    print('old position = ${details.data.table.offset}');
    key.currentState?.setState(() => null);
    details.data.table.offset = details.offset;
    print('new position = ${details.data.table.offset}');
    RenderObject? renderObject = key.currentContext?.findRenderObject();
    if (renderObject != null) {
      var translation = renderObject.getTransformTo(null).getTranslation();
      print('translation: x=${translation.x}, y= ${translation.y}');
    }
  }
}

class DBTable {
  GlobalKey key = GlobalKey();
  Offset offset = const Offset(0, 0);
  String name = '';
  List<String> columns = [];
}

class DBTableView extends StatefulWidget {
  final DBTable table;
  DBTableView({required this.table}) : super(key: table.key);

  @override
  State<StatefulWidget> createState() => _DBTableViewState();
}

class _DBTableViewState extends State<DBTableView> {
  @override
  Widget build(BuildContext context) {
    return Positioned(
      left: widget.table.offset.dx,
      top: widget.table.offset.dy,
      child: Draggable(
        data: widget,
        child: _buildChild(DragWidgetType.child),
        childWhenDragging: _buildChild(DragWidgetType.childLeft),
        feedback: Material(
          child: _buildChild(DragWidgetType.feedback),
        ),
      ),
    );
  }

  Widget _buildChild(DragWidgetType type) {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(),
        color: (type == DragWidgetType.child)
            ? Colors.amberAccent.shade200
            : (type == DragWidgetType.childLeft)
                ? Colors.black26
                : Colors.yellowAccent,
      ),
      padding: EdgeInsets.all(8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('- ${widget.table.name} -'),
          for (String col in widget.table.columns) Text(col),
        ],
      ),
    );
  }
}

enum DragWidgetType { child, childLeft, feedback }
4

0 回答 0