How to set offset between feedback and pointer when using `Draggable` in flutter?
Asked Answered
S

2

5

I'm trying to make fill-in-the-blank UI by using DragTarget and Draggable. I want to set offset between feedback and pointer during dragging to prevent the feedback from beeing hidden by a finger, and I need to do hit-testing between the feedback and the dragtarget How can I implement this? This is what I want to implement.

Solution

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  String _text = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Expanded(
            child: Center(
              child: _buildDragTarget(),
            ),
          ),
          Expanded(
            child: Center(
              child: _buildDraggable(),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDragTarget() {
    return DragTarget<String>(onAccept: (data) {
      setState(() {
        _text = data;
      });
    }, builder: (BuildContext context, List candidateData, List rejectedData) {
      return Container(
        width: 150,
        height: 50,
        decoration: BoxDecoration(
          border: Border.all(width: 3, color: Colors.blue),
        ),
        child: Center(
          child: Text(
            _text,
            style: TextStyle(fontSize: 24),
          ),
        ),
      );
    });
  }

  Widget _buildDraggable() {
    var draggable = Chip(
      label: Text(
        'draggable',
        style: TextStyle(fontSize: 24),
      ),
    );

    var feedback = Transform.scale(
      scale: 2.0,
      child: Opacity(
        opacity: 0.5,
        child: Container(
          padding: EdgeInsets.only(bottom: 100),
          child: Material(
              color: Colors.transparent,
              child: Transform.scale(
                scale: 0.5,
                child: draggable,
              )),
        ),
      ),
    );

    return Draggable<String>(
      dragAnchor: DragAnchor.child,
      child: draggable,
      feedback: feedback,
      feedbackOffset: Offset(0, -50),
      data: 'draggable',
    );
  }
}

This is the result.

Stillman answered 18/3, 2020 at 9:54 Comment(0)
T
4

An easier solution may be to add this function:

Offset myPointerDragAnchorStrategy(
    Draggable<Object> draggable, BuildContext context, Offset position) {
  return Offset(10, 0);
}

and then set the dragAnchorStrategy property in the Draggable object:

return Draggable<String>(
    ...
    dragAnchorStrategy: myPointerDragAnchorStrategy,
    ...
);
Tramontane answered 8/9, 2022 at 16:11 Comment(0)
R
2

In this case, I would suggest using the Transform widget to scale up the selected draggable item by a bit and use it as feedback. It will also give the user a feel that the item has been picked up.

Just wrap your draggable widget with Transform and use scale property with value ~1.25. (an example value) This will increase the size of the widget by 25%.

However, if you specifically need to add an offset for the picked Item, then just use a padded version of the draggable item as feedback.

For example,

If you need to add move the draggable a bit above the current touch position, then just add required padding below the draggable item.

Basically, by adding some padding in the opposite side, it gives you an effect of adding offset in the widget.

I would still suggest going for the Transform widget approach. It feels more genuine and is common in all similar UIs.

If you have any questions about this approach, let me know in the comments.

Risteau answered 18/3, 2020 at 10:51 Comment(1)
Thank you! I resolved it by using Transform and Padding, but I had to make more complicated widget than I thought...Stillman

© 2022 - 2024 — McMap. All rights reserved.