onTap和OnDrag - Flutter的偏移量不同

问题描述 投票:5回答:2

我有一个图像,其中某些项目有起始偏移及其高度和宽度,对应于图像中的每个项目我有不同的文本,我必须拖动文本并将其放到图像上的正确位置,我是在点击特定位置时获得不同的偏移量,同时拖动也会得到不同的偏移量。我怎样才能获得相同的偏移量?

这是我正在使用的代码和图像。这些是树的细节

x=673
y=635
h=214
w=149

关于形象。 enter image description here

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  ImageInfo _imageInfo;
  AssetImage assestImage;
  double dx;
  double dy;
  Offset dragOffset;
  @override
  void initState() {
    super.initState();
    assestImage = AssetImage('assets/hospital.jpg');
    WidgetsBinding.instance.addPostFrameCallback((a) => _getImageInfo());
  }

  void _getImageInfo() async {
    Image image = new Image.asset('assets/hospital.jpg');
    image.image
        .resolve(new ImageConfiguration())
        .addListener((ImageInfo info, bool _) {
      _imageInfo = info;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            DragTarget(
                onAccept: (Offset dragOffset) {},
                builder: (
                  BuildContext context,
                  List<dynamic> accepted,
                  List<dynamic> rejected,
                ) {
                  return TapImage(
                    onTap: (Offset offset) {
                      print('Offset on Tapping the image is $offset');
                      dx = offset.dx * _imageInfo.image.width;
                      dy = offset.dy * _imageInfo.image.height;
                      if (_imageInfo != null) {
                        print('Image clicked: ${dx.toInt()} x ${dy.toInt()}');
                        if ((673 <= dx && dx <= 822) &&
                            (635 <= dy && dy <= 849)) {
                          print('you drop in tree');
                        } else {}
                      }
                    },
                    image: assestImage,
                  );
                }),
            Draggable(
                dragAnchor: DragAnchor.pointer,
                onDragEnd: (details) {
                  setState(() {
                    dragOffset = details.offset;
                  });
                  print('dragoffset in onDrag Method is  $dragOffset');
                },
                data: dragOffset,
                child: Container(
                    color: Colors.green,
                    child: Text(
                      'Tree',
                      style: TextStyle(fontSize: 30.0),
                    )),
                feedback: Container(
                  height: 10.0,
                  child: Text(
                    'Tree',
                    style: TextStyle(fontSize: 15.0),
                  ),
                )),
          ],
        ),
      ),
    );
  }
}

typedef void OnTapLocation(Offset offset);

class TapImage extends StatelessWidget {
  TapImage({Key key, this.onTap, this.image}) : super(key: key);

  final OnTapLocation onTap;
  final ImageProvider image;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (TapDownDetails details) => _onTap(details, context),
      onLongPress: () {},
      child: Image(image: AssetImage('assets/hospital.jpg')),
    );
  }

  void _onTap(TapDownDetails details, BuildContext context) {
    RenderBox getBox = context.findRenderObject();
    Offset local = getBox.globalToLocal(details.globalPosition);
    print('locla ois $local');
    onTap(Offset(local.dx / getBox.size.width, local.dy / getBox.size.height));
  }
}
dart flutter flutter-layout
2个回答
3
投票

它为我工作

class _HomeState extends State<Home> {
  ImageInfo _imageInfo;
  AssetImage assestImage;
  double getheight;
  double getywidth;

  Offset dragOffset;
  @override
  void initState() {
    super.initState();
    assestImage = AssetImage('assets/hospital.jpg');
    WidgetsBinding.instance.addPostFrameCallback((a) => _getImageInfo());
  }

  void _getImageInfo() async {
    Image image = new Image.asset('assets/hospital.jpg');
    image.image
        .resolve(new ImageConfiguration())
        .addListener((ImageInfo info, bool _) {
      _imageInfo = info;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          child: Column(
        children: <Widget>[
          TapImage(
            onTap: (Offset offset, RenderBox getBox, TapDownDetails details) {
              double dx;
              double dy;
              dx = offset.dx * _imageInfo.image.width;
              dy = offset.dy * _imageInfo.image.height;
              setState(() {
                dragEnd(dx, dy);
              });
            },
            image: assestImage,
          ),
          Draggable(
              dragAnchor: DragAnchor.pointer,
              onDragStarted: () {
                WidgetsBinding.instance
                    .addPostFrameCallback((_) => setState(() {
                          RenderBox getBox = context.findRenderObject();
                          getheight = getBox.size.height;
                          getywidth = getBox.size.width;
                        }));
              },
              onDragEnd: (details) {
                double dx;
                double dy;
                dx = (details.offset.dx / getywidth) * _imageInfo.image.width;
                dy =
                    ((details.offset.dy) / getywidth) * _imageInfo.image.height;
                setState(() {
                  dragEnd(dx, dy);
                });
              },
              child: Padding(
                padding: const EdgeInsets.only(top: 28.0),
                child: Container(
                    color: Colors.green,
                    child: Text(
                      'tree',
                      style: TextStyle(fontSize: 30.0),
                    )),
              ),
              feedback: Container(
                height: 10.0,
                child: Text(
                  'tree',
                  style: TextStyle(fontSize: 15.0),
                ),
              )),
        ],
      )),
    );
  }

  void dragEnd(double dx, double dy) {
    if (_imageInfo != null) {
      if ((673 <= dx && dx <= 822) && (635 <= dy && dy <= 849)) {
        showDialog(
          context: context,
          builder: (context) {
            return _textDescriptionDialog(
              context,
              'Drag on tree',
            );
          },
        );
      } else {
        showDialog(
          context: context,
          builder: (context) {
            return _textDescriptionDialog(
              context,
              'Drag outside',
            );
          },
        );
      }
    }
  }

  Widget _textDescriptionDialog(BuildContext context, String text) {
    return new FractionallySizedBox(
        heightFactor: MediaQuery.of(context).orientation == Orientation.portrait
            ? 0.5
            : 0.8,
        widthFactor: MediaQuery.of(context).orientation == Orientation.portrait
            ? 0.8
            : 0.4,
        child: Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(20.0),
            ),
          ),
          child: Container(child: Center(child: Text(text))),
        ));
  }
}

typedef void OnTapLocation(
    Offset offset, RenderBox getBox, TapDownDetails details);

class TapImage extends StatelessWidget {
  TapImage({Key key, this.onTap, this.image}) : super(key: key);

  final OnTapLocation onTap;
  final ImageProvider image;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (TapDownDetails details) => _onTap(details, context),
      child: Image(image: AssetImage('assets/hospital.jpg')),
    );
  }

  void _onTap(TapDownDetails details, BuildContext context) {
    RenderBox getBox = context.findRenderObject();
    print('size is ${getBox.size}');
    Offset local = getBox.globalToLocal(details.globalPosition);
    print('local is $local');
    onTap(Offset(local.dx / getBox.size.width, local.dy / getBox.size.height),
        getBox, details);
  }
}

2
投票

您可以制作新的Widget,然后获取本地渲染框大小。像这样的东西:

class _MyHomePageState extends State<MyHomePage> {
  NetworkImage _networkImage;
  ImageInfo _imageInfo;

  @override
  void initState() {
    super.initState();

    _networkImage = NetworkImage('https://i.stack.imgur.com/2PnTa.jpg');
    _getImageInfo();
  }

  void _getImageInfo() async {
    NetworkImage _key = await _networkImage.obtainKey(ImageConfiguration());
    _networkImage.load(_key).addListener((ImageInfo i, bool b){
      print('Image size: ${i.image.width} - ${i.image.height}');
      _imageInfo = i;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ImageDetector(
          onTap: (Offset offset){
            if(_imageInfo != null){
              print('Image clicked: ${offset.dx * _imageInfo.image.width} x ${offset.dy * _imageInfo.image.height}');
            }
          },
          image: _networkImage,
        ),
      ),
    );
  }
}

typedef void OnTapLocation(Offset offset);

class ImageDetector extends StatelessWidget {
  ImageDetector({Key key, this.onTap, this.image}) : super(key: key);

  final OnTapLocation onTap;
  final ImageProvider image;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (TapDownDetails details) => _onTap(details, context),
      child: Image(image: image),
    );
  }


  void _onTap(TapDownDetails details, BuildContext context) {
    RenderBox getBox = context.findRenderObject();
    Offset local = getBox.globalToLocal(details.globalPosition);

    print('Clicked on: ${local.dx / getBox.size.width} - ${local.dy / getBox.size.height}');
    onTap(Offset(local.dx / getBox.size.width, local.dy / getBox.size.height));
  }
}

这将返回0.0,0.0和1.0,1.0之间的点击位置,您可以获得图像的大小并从中获取准确的位置。

编辑:更新代码

© www.soinside.com 2019 - 2024. All rights reserved.