在卡片中任意定位小部件(基于相对于父级的 xy 坐标)

Har*_*dia 5 dart flutter

我想要在卡片上放置一个点,可以在卡片内任意移动。

这是我到目前为止的解决方案。

class RoomCard extends StatefulWidget {
  final Room room;

  RoomCard({
    @required this.room,
  }) : assert(room != null);

  @override
  _RoomCardState createState() => _RoomCardState();
}

class _RoomCardState extends State<RoomCard> {
  double x = 0.0;
  double y = 0.0;
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 400.0,
      width: 400.0,
      child: GestureDetector(
        onPanUpdate: (p) {
          setState(() {
            x += p.delta.dx;
            y += p.delta.dy;
          });
        },
        child: Card(
          child: Stack(
            children: <Widget>[
              Marker(
                x: x,
                y: y,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Marker extends StatelessWidget {
  final double x;
  final double y;

  Marker({this.x: 0.0, this.y: 0.0});

  @override
  Widget build(BuildContext context) {
    print("x: $x, y: $y");
    return Padding(
      padding: EdgeInsets.only(left: x, top: y),
      child: CircleAvatar(),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

除了使用 Padding 小部件来执行此操作之外,我找不到任何其他方法可以根据 x,y 位置将标记放置在卡片中。让我知道是否还有其他更好的方法。

其次,这是第一次工作(第一次移动它)。之后移动时遇到问题。我在这里缺少任何逻辑吗?

我想进一步扩展它,在卡片上有多个这样的点,可以随意放置和移动。

如果您能推荐任何可以执行此操作的第 3 方软件包,我会很高兴。

Sae*_*bil 5

你可以像下面这样使用 Transform

  class Marker extends StatelessWidget {
    final double x;
    final double y;

    Marker({this.x: 0.0, this.y: 0.0});

    @override
    Widget build(BuildContext context) {
      print("x: $x, y: $y");

      return Transform(
          transform: Matrix4.translationValues(x, y, 0.0), child: CircleAvatar());
    }
  }
Run Code Online (Sandbox Code Playgroud)

您需要检查 x,y 约束以将变换限制到某个区域

编辑:

这是一个完整的工作代码,说明如何将标记限制在卡片的底部边缘

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(new MaterialApp(
    home: new Scaffold(
      body: RoomCard(room: Room()),
    ),
  ));
}

class Room {}

class RoomCard extends StatefulWidget {
  final Room room;

  RoomCard({
    @required this.room,
  }) : assert(room != null);

  @override
  _RoomCardState createState() => _RoomCardState();
}

class _RoomCardState extends State<RoomCard> {
  double x = 0.0;
  double y = 0.0;

  @override
  Widget build(BuildContext context) {

    //This hight should be known or calculated for the Widget need to be moved
    const double markerHight = 50.0;

    double ymax = context.findRenderObject()?.paintBounds?.bottom ?? markerHight ;


    return SizedBox(
      height: 300.0,
      width: 400.0,
      child: GestureDetector(
        onPanUpdate: (p) {
          setState(() {
            x += p.delta.dx;
            y = (y+p.delta.dy) >ymax - markerHight ? ymax -markerHight : y+p.delta.dy;

          });
        },
        child: Card(
          child: Stack(
            children: <Widget>[

              Marker(
                x: x,
                y: y,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

      class Marker extends StatelessWidget {
        final double x;
        final double y;

        Marker({this.x: 0.0, this.y: 0.0});

        @override
        Widget build(BuildContext context) {
          print("x: $x, y: $y");
          return Transform(
              transform: Matrix4.translationValues(x, y, 0.0), 
              child: CircleAvatar());
        }
      }
Run Code Online (Sandbox Code Playgroud)