Mainly complete the boiling point page of the topic square page. This page involves content including: drag and drop sort, add topic animation effect, first analyze how the effect is implemented, and then is the page construction. The final result

Drag and drop

The first thought of a drag is that a flutter provides a ReorderableListView drag effect:

var data = <Color>[
    Colors.yellow[50],
    Colors.blue[100],
    Colors.red[200],
    Colors.pink[300]];@override
  Widget build(BuildContext context) {
    return Container(
      height: 250,
      child: ReorderableListView(
        padding: EdgeInsets.all(10),
        onReorder: _handleReorder,
        scrollDirection: Axis.vertical,
        children: data.map((color) => _buildItem(color)).toList(),
      ),
    );
  }

  void _handleReorder(int oldIndex, int newIndex) {
    if (oldIndex < newIndex) {
      newIndex -= 1;
    }

    setState(() {
      final element = data.removeAt(oldIndex);
      data.insert(newIndex, element);
    });
  }

  Widget _buildItem(Color color) {
    return Container(
      key: ValueKey(color),
      alignment: Alignment.center,
      height: 50,
      width: 200,
      color: color,
    );
  }
Copy the code

Also use GridView and LongPressDraggable for drag sorting

renderItem(index) {
    return Stack(
      children: [
        Container(
          decoration: BoxDecoration(
            color: Colors.white,
            border: Border.all(color: Colors.grey, width: 1),
            borderRadius: BorderRadius.circular(15),
          ),
          alignment: Alignment.center,
          child: Text(widget.dataList[index]['title']),
        ),
        Positioned(
          child: Text(widget.dataList[index]['move'] = ='false' ? 'x' : '+'),
          right: 10,
          top: 2,)]); } Widget _buildItemWidget(int index) {
    return LongPressDraggable(
      data: index,
      child: DragTarget<int>(
        onAccept: (data) {
          widget.onAccept(data, index);
        },
        builder: (context, data, rejects) {
          return renderItem(index);
        },
        onMove: (data) {
          print(data);
        },
        onLeave: (data) {
          print('$data is Leaving item $index');
          widget.onAccept(data, index);
        },
        onWillAccept: (data) {
          return true;
        },
      ),
      onDragStarted: () {
      },
      onDraggableCanceled: (Velocity velocity, Offset offset) {
      },
      onDragCompleted: () {
      },
     
      feedback: Material(
        child: Container(
          width: (Get.width - 20 - 20) / 3.0,
          height: (Get.width - 20 - 20) / 3.0 * 4 / 10,
          child: renderItem(index),
        ),
      ),
      childWhenDragging: Container(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            childAspectRatio: 2.5,
            crossAxisSpacing: 10,
            mainAxisSpacing: 10),
        itemCount: widget.dataList.length,
        itemBuilder: (BuildContext context, int index) {
          return _buildItemWidget(index);
        });
  }
Copy the code

Both effects can achieve the requirements, no ideas to see how the gods are written. Look at the source code, there is a use of GridView with gesture recognition operation. Use the DragabLegridView_FLUTTER library and modify the portal slightly. I have no ideas to search for. For those with implementations, read the code. Gradually, I can build my own wheels.

 List<ItemBin> itemBins = new List(a);var editSwitchController = EditSwitchController();
DragAbleGridView(
                    mainAxisSpacing: 10.0,
                    crossAxisSpacing: 0.0,
                    childAspectRatio: 2.5,
                    crossAxisCount: 3, itemBins: itemBins, editSwitchController: editSwitchController, isOpenDragAble: alert ! ='Click on the topic',
                    animationDuration: 300.//milliseconds
                    longPressDuration: 800.//milliseconds

                    child: (int position) {
                      return Container(
                        width: (Get.width - 60) / 3.0,
                        height: (Get.width - 40) / 3.0 * 0.4.// margin: EdgeInsets. Only (top: 6.0, right: 6.0),
                        decoration: BoxDecoration(
                          color: Colors.white,
                          border: Border.all(color: Colors.grey, width: 1),
                          borderRadius: BorderRadius.circular(15),
                        ),
                        alignment: Alignment.center,
                        child: Text(
                          itemBins[position].data,
                          style: TextStyle(fontSize: 16.0, color: Colors.blue),
                        ),
                      );
                    },
                    editChangeListener: () {},
                  ),
                ),
Copy the code

Shake up

Just use the tween animation and hit Edit to animate the editable one

controller = AnimationController(
        duration: const Duration(milliseconds: 1000), vsync: this);

    animation = TweenSequence<double> ([// Use TweenSequence for multi-group tween animation
      TweenSequenceItem<double>(tween: Tween(begin: 0, end: 5), weight: 1),
      TweenSequenceItem<double>(tween: Tween(begin: 5, end: 0), weight: 2),
      TweenSequenceItem<double>(tween: Tween(begin: 0, end: - 5), weight: 3),
      TweenSequenceItem<double>(tween: Tween(begin: - 5, end: 0), weight: 4), ]).animate(controller) .. addListener(() { setState(() {}); }).. addStatusListener((s) {if (s == AnimationStatus.completed) {
          setState(() {});
          // controller.forward();}}); Transform( transform: Matrix4.rotationZ(animation.value * pi /180),
                          alignment: Alignment.center,
                          child: Container(
                            width: (Get.width - 60) / 3.0,
                            height: (Get.width - 40) / 3.0 * 0.4,
                            margin: EdgeInsets.only(top: 6.0),
                            decoration: BoxDecoration(
                              color: Colors.white,
                              border: Border.all(color: Colors.grey, width: 1),
                              borderRadius: BorderRadius.circular(15),
                            ),
                            alignment: Alignment.center,
                            child: Text(
                              itemBins[position].data,
                              style:
                                  TextStyle(fontSize: 16.0, color: Colors.blue),
                            ),
                          ));
Copy the code

Add Topic Linkage

Add topic at the bottom, delete topic in my topic. Linkage effect, relatively simple to achieve, is the final effect.

// The default value is 5
CommonListWiget(
            networkApi: (currentPage) async {
              return ['1'.'2'.'3'.'4'.'5'];
            },
            itemBuilder: (BuildContext context, int position) {
            / /... I left out the code
            // Finally return:
                Wrap(
                children: futureList
                    .map((e) => Stack(
                          children: [
                            InkWell(
                              onTap: () {
                                futureList.remove(e);
                                currentList.add(e);
                                itemBins.add(new ItemBin(e));
                                // setState(() {});
                              },
                              child: Container(
                                margin: EdgeInsets.only(
                                    bottom: 10, right: 10, left: 10, top: 5),
                                width: (Get.width - 60) / 3.0,
                                height: (Get.width - 40) / 3.0 * 0.4,
                                decoration: BoxDecoration(
                                  color: Colors.white,
                                  border:
                                      Border.all(color: Colors.grey, width: 1),
                                  borderRadius: BorderRadius.circular(15),
                                ),
                                alignment: Alignment.center,
                                child: Text(e,
                                    style: TextStyle(
                                        fontSize: 16.0, color: Colors.blue)),
                              ),
                            ),
                            Positioned(
                              child: Text(
                                '+',
                                style: TextStyle(fontSize: 18),
                              ),
                              top: 5,
                              right: 20,
                            )
                          ],
                        ))
                    .toList(),
              );
            }
Copy the code