caduandrade / tabbed_view

Widget inspired by the classic Desktop-style tab component.
MIT License
49 stars 16 forks source link

drag drop sample code #20

Closed bksubhuti closed 1 year ago

bksubhuti commented 1 year ago

Is there complete sample code to make drag and drop work? I have implemented drag from the sample code in my project, but I do not see a fully function sample to make drop work Can you provide this? It is essential for managing multi view documents for our app on our desktop and tablet view versions so they can be organized like any browser allows. (project released in production: tipitaka pali reader).

caduandrade commented 1 year ago

Hi @bksubhuti!

You will need another Widget as a "drop area". This Widget is the DragTarget.

You can see more at https://api.flutter.dev/flutter/widgets/Draggable-class.html and https://api.flutter.dev/flutter/widgets/DragTarget-class.html.

I will update the demo with a complete example like this:

class ExampleStateful extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => ExampleState();
}

class ExampleState extends State<ExampleStateful> {
  String? _acceptedData;
  late TabbedViewController _controller;

  @override
  void initState() {
    List<TabData> tabs = [];
    for (var i = 1; i < 7; i++) {
      Widget tabContent = Center(child: Text('Content $i'));
      tabs.add(TabData(text: 'Tab $i', content: tabContent));
    }
    _controller = TabbedViewController(tabs);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    TabbedView tabbedView = TabbedView(
        controller: _controller,
        draggableTabBuilder: (int tabIndex, TabData tab, Widget tabWidget) {
          return Draggable<String>(
              child: tabWidget,
              feedback: Material(
                  child: Container(
                      child: Text(tab.text),
                      padding: EdgeInsets.all(4),
                      decoration: BoxDecoration(border: Border.all()))),
              data: tab.text,
              dragAnchorStrategy: (Draggable<Object> draggable,
                  BuildContext context, Offset position) {
                return Offset.zero;
              });
        });

    DragTarget<String> dragTarget = DragTarget(
      builder: (
        BuildContext context,
        List<dynamic> accepted,
        List<dynamic> rejected,
      ) {
        return Container(
          padding: EdgeInsets.all(8),
          color: Colors.yellow[100],
          child: Center(
              child: ListTile(
                  title: Text('Drop here'),
                  subtitle: Text('Last dropped tab: ${_acceptedData ?? ''}'))),
        );
      },
      onAccept: (String data) {
        setState(() {
          _acceptedData = data;
        });
      },
    );

    return Column(children: [
      Expanded(child: tabbedView, flex: 3),
      Flexible(child: dragTarget, flex: 1)
    ], crossAxisAlignment: CrossAxisAlignment.stretch);
  }
}

Good luck with the tipitaka pali reader :wink:

Let me know if you need anything else.

bksubhuti commented 1 year ago

Hi... I did the sample code. The widest use case would be to have the tabs re-order. Like you would do in a browser. That too is our need. We have an icon dropped into our tab.. and use that as a drop target, however, there are 2 problems 1.) Very small area for drag target. 2) There is a lot of fuss as to having the tab to drop in focus.
3) So to make this work, one must first decide the target.. click and have that focus, then go back to the originated drag source and then drag to that tab.. but one must be very careful to see the very small icon change color to let you know it can accept.

The expectation is to have re-order of tabs work like any browser, chrome, vivaldi etc. So that we can reorder the tabs. The issue is we don't have access to the main tab Text() widget to make it a drag target. We also have a small icon we drop inside but it is too small. The code is pushed if you want to see our implementation. tipitaka pali reader