draggable_container 1.0.6 copy "draggable_container: ^1.0.6" to clipboard
draggable_container: ^1.0.6 copied to clipboard

outdated

A Very Smooth Draggable Widget Container. Each children is Draggable, Deletable and Fixable. Support SliverGridDelegate!

example/lib/main.dart

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

import 'data.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DraggableContainer In ListView',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyItem extends DraggableItem {
  final Color color;
  final int index;
  bool deletable;
  bool fixed;

  MyItem({
    @required this.index,
    this.deletable = true,
    this.fixed = false,
    Color color,
  }) : color = color ?? randomColor();

  @override
  String toString() {
    return '<MyItem> {index:$index, fixed:$fixed, deletable:$deletable}';
  }
}

class AddItem extends DraggableItem {
  @override
  bool get deletable => false;

  @override
  bool get fixed => true;

  @override
  String toString() {
    return '<AddItem> {fixed:$fixed, deletable:$deletable}';
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePage createState() => _MyHomePage();
}

class _MyHomePage extends State<MyHomePage> {
  final data = <DraggableItem>[
    MyItem(index: 0),
    MyItem(index: 1),
    MyItem(index: 2),
    MyItem(index: 3),
    AddItem(),
  ];

  final key = GlobalKey<DraggableContainerState<DraggableItem>>();

  String items = '';
  String delegate = '';
  String settings = '';

  updateText() {
    if (key.currentState != null) {
      Map<String, dynamic> text = {};
      var widget = key.currentWidget as DraggableContainer;
      var _delegate = widget.gridDelegate;
      if (_delegate is SliverGridDelegateWithFixedCrossAxisCount) {
        text['SliverGridDelegateWithFixedCrossAxisCount'] = '';
        text['crossAxisCount'] = _delegate.crossAxisCount;
        text['crossAxisSpacing'] = _delegate.crossAxisSpacing;
        text['mainAxisSpacing'] = _delegate.mainAxisSpacing;
      } else if (_delegate is SliverGridDelegateWithMaxCrossAxisExtent) {
        text['SliverGridDelegateWithMaxCrossAxisExtent'] = '';
        text['maxCrossAxisExtent'] = _delegate.maxCrossAxisExtent;
        text['crossAxisSpacing'] = _delegate.crossAxisSpacing;
        text['mainAxisSpacing'] = _delegate.mainAxisSpacing;
      }
      delegate = mapToString(text);

      text.clear();
      text['tapOutSideExitEditMode'] = key.currentState.tapOutSideExitEditMode;
      text['onChange listener'] = widget.onChanged == null ? 'unset' : 'set';
      text['beforeRemove listener'] =
          widget.beforeRemove == null ? 'unset' : 'set';
      text['beforeDrop listener'] = widget.beforeDrop == null ? 'unset' : 'set';
      settings = mapToString(text);

      items = key.currentState?.items?.join('\n');
    }
  }

  Future<bool> beforeRemove(item, int slotIndex) async {
    item = item as MyItem;
    final res = await showDialog<bool>(
        context: context,
        builder: (_) => AlertDialog(
              title: Text('Remove item ${item.index}?'),
              actions: [
                TextButton(
                    onPressed: () => Navigator.pop(context, false),
                    child: Text('No')),
                ElevatedButton(
                    onPressed: () => Navigator.pop(context, true),
                    child: Text('Yes')),
              ],
            ));
    if (res == true) {
      key.currentState.removeSlot(slotIndex);
    }
    return false;
  }

  String mapToString(Map map) {
    return map.keys.map((key) => '$key: ${map[key]}').join('\n');
  }

  @override
  Widget build(BuildContext context) {
    updateText();
    return Scaffold(
      appBar: AppBar(
        title: Text('DraggableContainer In ListView'),
      ),
      body: ListView(
        children: [
          ListTile(
            title: Text('DraggableContainer settings'),
            subtitle: Text(settings),
          ),
          Divider(height: 1),
          ListTile(
            title: Text('Current SliverGridDelegate'),
            subtitle: Text(delegate),
          ),
          Divider(height: 1),
          DraggableContainer<DraggableItem>(
            key: key,
            items: data,
            beforeRemove: beforeRemove,
            draggingDecoration: BoxDecoration(boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.3),
                blurRadius: 5,
                offset: Offset(0, 5),
              ),
            ]),
            // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            //   crossAxisCount: 3,
            //   crossAxisSpacing: 10,
            //   mainAxisSpacing: 10,
            // ),
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 150,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
            ),
            padding: EdgeInsets.all(10),
            onChanged: (List<DraggableItem> items) {
              final addItem = items.firstWhere(
                (item) => item is AddItem,
                orElse: () => null,
              );
              // print('has AddItem ${addItem != null}');
              if (items.length < 9 && addItem == null)
                key.currentState.addSlot(AddItem());
              setState(() {});
            },
            beforeDrop: ({fromItem, fromSlotIndex, toItem, toSlotIndex}) {
              // print('beforeDrop from $fromSlotIndex to $toSlotIndex');
              /// will override the toItem.fixed property
              return Future.value(true);
            },
            itemBuilder: (_, DraggableItem item) {
              if (item is AddItem) {
                return ElevatedButton(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(
                        'Add',
                        style: TextStyle(color: Colors.white),
                      ),
                      Icon(
                        Icons.add,
                        color: Colors.white,
                      ),
                    ],
                  ),
                  onPressed: () {
                    if (key.currentState.slots.length < 9) {
                      key.currentState.insertSlot(
                          0,
                          MyItem(
                            index: key.currentState.slots.length,
                          ));
                    } else {
                      print('replace 8');
                      key.currentState.replaceItem(8, MyItem(index: 99));
                    }
                  },
                );
              } else if (item is MyItem) {
                return Material(
                  elevation: 0,
                  borderOnForeground: false,
                  child: Container(
                    color: item.color,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          item.index.toString(),
                          style: TextStyle(
                            fontSize: 22,
                            color: Colors.white,
                            shadows: [
                              BoxShadow(color: Colors.black, blurRadius: 5),
                            ],
                          ),
                        ),
                        SizedBox(height: 5),
                        ElevatedButton.icon(
                          icon: Icon(item.fixed
                              ? Icons.lock_outline
                              : Icons.lock_open),
                          label: Text(item.fixed ? 'Unlock' : 'Lock'),
                          onPressed: () {
                            item.fixed = !item.fixed;
                            setState(() {});
                          },
                        ),
                      ],
                    ),
                  ),
                );
              }
              return null;
            },
          ),
          Divider(height: 1),
          ListTile(
            title: Text('Current Items'),
            subtitle: Text(items),
          ),
        ],
      ),
    );
  }
}
26
likes
0
pub points
63%
popularity

Publisher

unverified uploader

A Very Smooth Draggable Widget Container. Each children is Draggable, Deletable and Fixable. Support SliverGridDelegate!

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on draggable_container