drag_and_drop_gridview

pub package Awesome Flutter Buy Me A Coffee

Drag And Drop GridView 扩展了 Flutter 中 GridView 小部件的功能,让您可以通过简单的拖放来重新排列 GridView 的项目。它非常容易实现,并且使用起来很美观。

如果您欣赏此内容,请通过 ?| ⭐| ? 来支持项目的可见性!

用法

要使用此 ,请将 drag_and_drop_gridview 添加到您的 pubspec.yaml 文件中作为 依赖项

dependencies:
  drag_and_drop_gridview: ^1.0.8

并在您的代码中导入该包。

import 'package:drag_and_drop_gridview/devdrag.dart';

示例

概述

DragAndDropGridView 具有 GridView.builder 构造函数 的所有相同参数(除了 shrinkWrapscrollDirection)。

但在 DragAndDropGridView 中,有一些必需的参数:gridDelegateitemBuilderonWillAcceptonReorder

gridDelegate

这与我们在 Flutter 的官方 GridView 中找到的相同。 了解更多

gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 3 / 4.5,
     ),

itemBuilder

这与我们在 Flutter 的官方 GridView 中找到的相同。 了解更多

itemBuilder: (context, index) => Card(
       elevation: 2,
       child: Text(_animals[index]),
),

onWillAccept

此函数允许您验证是否要接受 gridViewItems 顺序的更改。如果您总是想接受更改,只需 return true

// _animals = ['cat','dog','kitten','puppy']

onWillAccept: (oldIndex, newIndex) {
// Implement you own logic

// Example reject the reorder if the moving item's value is "kitten" 
if (_animals[newIndex] == "cat"){
	return false;
}
return true, // If you want to accept the child return true or else return false
},

onReorder

此函数处理新排列的 gridItems 索引的更改。

onReorder: (oldIndex, newIndex) {
	    _temp = _animals[newIndex];
        _animals[newIndex] = _animals[oldIndex];
        _animals[oldIndex] = _temp;
        setState(() {});
},

示例

 _animals = ['cat','dog','kitten','puppy']
 
DragAndDropGridView(
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 3 / 4.5,
    ),
    padding: EdgeInsets.all(20),
    itemBuilder: (context, index) => Card(
        elevation: 2,
        child: Text(_animals[index]),
		),
    ),
    itemCount: _animals.length,
    onWillAccept: (oldIndex, newIndex) {
		// Implement you own logic

		// Example reject the reorder if the moving item's destination value is cat"
		if (_animals[newIndex] == "cat"){
			return false;
		}
		return true, // If you want to accept the child return true or else return false
	},
    onReorder: (oldIndex, newIndex) {
	    _temp = _animals[newIndex];
        _animals[newIndex] = _animals[oldIndex];
        _animals[oldIndex] = _temp;
        setState(() {});
    },
)

示例 #1:DragAndDropGridView

以下示例向您展示了如何轻松实现 DragAndDropGridView

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
  ];

  int variableSet = 0;
  ScrollController _scrollController;
  double width;
  double height;

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Drag And drop Plugin'),
        ),
        body: Center(
          child: DragAndDropGridView(
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(20),
            itemBuilder: (context, index) => Card(
              elevation: 2,
              child: LayoutBuilder(
                builder: (context, costrains) {
                  if (variableSet == 0) {
                    height = costrains.maxHeight;
                    width = costrains.maxWidth;
                    variableSet++;
                  }
                  return GridTile(
                    child: Image.network(
                      _imageUris[index],
                      fit: BoxFit.cover,
                      height: height,
                      width: width,
                    ),
                  );
                },
              ),
            ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) {
              // Implement you own logic

              // Example reject the reorder if the moving item's value is something specific
              if (_imageUris[newIndex] == "something") {
                return false;
              }
              return true; // If you want to accept the child return true or else return false
            },
            onReorder: (oldIndex, newIndex) {
              final temp = _imageUris[oldIndex];
              _imageUris[oldIndex] = _imageUris[newIndex];
              _imageUris[newIndex] = temp;

              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果


示例 #2:DragAndDropGridView Horizontal (可重排)

这是关于如何实现 水平可重排/重新索引 功能的示例 DragAndDropGridView。只需使用 horizontal 构造函数。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:drag_and_drop_gridview/drag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
  ];

  int variableSet = 0, variableSetHeader = 0;
  ScrollController _scrollController;
  double width;
  double height;

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Horizontal DragAndDropGridView'),
        ),
        body: Center(
          child: DragAndDropGridView.horizontal(
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 5,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(20),
            itemBuilder: (context, index) => Card(
              elevation: 2,
              child: LayoutBuilder(builder: (context, costrains) {
                if (variableSet == 0) {
                  height = costrains.maxHeight;
                  width = costrains.maxWidth;
                  variableSet++;
                }
                return GridTile(
                  key: index == 4 ? Key("12") : null,
                  child: Image.network(
                    _imageUris[index],
                    fit: BoxFit.cover,
                    height: height,
                    width: width,
                  ),
                );
              }),
            ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) => true,
            onReorder: (oldIndex, newIndex) {
              int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
              int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);

              if (indexOfFirstItem > indexOfSecondItem) {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i > _imageUris.indexOf(_imageUris[newIndex]);
                    i--) {
                  var tmp = _imageUris[i - 1];
                  _imageUris[i - 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              } else {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i < _imageUris.indexOf(_imageUris[newIndex]);
                    i++) {
                  var tmp = _imageUris[i + 1];
                  _imageUris[i + 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              }
              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果

示例 #3:DragAndDropGridView Vertical (可重排)

这是关于如何实现 垂直可重排/重新索引 功能的示例 DragAndDropGridView。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
  ];

  int variableSet = 0;
  ScrollController _scrollController;
  double width;
  double height;

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Vertical Drag And drop Plugin'),
        ),
        body: Center(
          child: DragAndDropGridView(
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(20),
            itemBuilder: (context, index) => Card(
              elevation: 2,
              child: LayoutBuilder(builder: (context, costrains) {
                if (variableSet == 0) {
                  height = costrains.maxHeight;
                  width = costrains.maxWidth;
                  variableSet++;
                }
                return GridTile(
                  child: Image.network(
                    _imageUris[index],
                    fit: BoxFit.cover,
                    height: height,
                    width: width,
                  ),
                );
              }),
            ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) => true,
            onReorder: (oldIndex, newIndex) {
            
              // You can also implement on your own logic on reorderable
              
              int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
              int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);

              if (indexOfFirstItem > indexOfSecondItem) {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i > _imageUris.indexOf(_imageUris[newIndex]);
                    i--) {
                  var tmp = _imageUris[i - 1];
                  _imageUris[i - 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              } else {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i < _imageUris.indexOf(_imageUris[newIndex]);
                    i++) {
                  var tmp = _imageUris[i + 1];
                  _imageUris[i + 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              }
              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果


示例 #4:DragAndDropGridView 带有悬停效果 (可重排)

这是关于如何实现 在悬停特定索引时重新排序效果 功能的示例 DragAndDropGridView。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
 
import 'package:flutter/services.dart';
 
void main() {
 runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
 @override
 _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 List<String> _imageUris = [
   "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
   "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
 ];
 
 int pos;
 
 List<String> tmpList;
 int variableSet = 0;
 ScrollController _scrollController;
 double width;
 double height;
 
 @override
 void initState() {
   tmpList = [..._imageUris];
   super.initState();
 }
 
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: Scaffold(
       appBar: AppBar(
         title: const Text('Vertical DragAndDropGridView Hover Effect'),
       ),
       body: Center(
         child: DragAndDropGridView(
           controller: _scrollController,
           gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
             crossAxisCount: 2,
             childAspectRatio: 3 / 4.5,
           ),
           padding: EdgeInsets.all(20),
           itemBuilder: (context, index) => Opacity(
             opacity: pos != null ? pos == index ? 0.6 : 1 : 1,
             child: Card(
               elevation: 2,
               child: LayoutBuilder(builder: (context, costrains) {
                 if (variableSet == 0) {
                   height = costrains.maxHeight;
                   width = costrains.maxWidth;
                   variableSet++;
                 }
                 return GridTile(
                   child: Image.network(
                     _imageUris[index],
                     fit: BoxFit.cover,
                     height: height,
                     width: width,
                   ),
                 );
               }),
             ),
           ),
           itemCount: _imageUris.length,
           onWillAccept: (oldIndex, newIndex) {
             _imageUris = [...tmpList];
             int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
             int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);
 
             if (indexOfFirstItem > indexOfSecondItem) {
               for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                   i > _imageUris.indexOf(_imageUris[newIndex]);
                   i--) {
                 var tmp = _imageUris[i - 1];
                 _imageUris[i - 1] = _imageUris[i];
                 _imageUris[i] = tmp;
               }
             } else {
               for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                   i < _imageUris.indexOf(_imageUris[newIndex]);
                   i++) {
                 var tmp = _imageUris[i + 1];
                 _imageUris[i + 1] = _imageUris[i];
                 _imageUris[i] = tmp;
               }
             }
 
             setState(
               () {
                 pos = newIndex;
               },
             );
             return true;
           },
           onReorder: (oldIndex, newIndex) {
             _imageUris = [...tmpList];
             int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
             int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);
 
             if (indexOfFirstItem > indexOfSecondItem) {
               for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                   i > _imageUris.indexOf(_imageUris[newIndex]);
                   i--) {
                 var tmp = _imageUris[i - 1];
                 _imageUris[i - 1] = _imageUris[i];
                 _imageUris[i] = tmp;
               }
             } else {
               for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                   i < _imageUris.indexOf(_imageUris[newIndex]);
                   i++) {
                 var tmp = _imageUris[i + 1];
                 _imageUris[i + 1] = _imageUris[i];
                 _imageUris[i] = tmp;
               }
             }
             tmpList = [..._imageUris];
             setState(
               () {
                 pos = null;
               },
             );
           },
         ),
       ),
     ),
   );
 }
}

结果


示例 #5:DragAndDropGridView 非粘性页眉

在此示例中,您可以添加一个非粘性页眉。

但是,如果您传入任何垂直滚动视图,请不要忘记添加 shrinkwrap 或将小部件包装在 expanded 中以避免错误。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:drag_and_drop_gridview/drag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
  ];

  int variableSet = 0, variableSetHeader = 0;
  ScrollController _scrollController;
  double width;
  double height;
  double widthHeader;
  double heightHeader;
  List<String> listOfHeader = ["1", "2"];

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('DragAndDropGridView'),
        ),
        body: Center(
          child: DragAndDropGridView(
            header: Container(
              height: 50,
              width: double.infinity,
              alignment: Alignment.center,
              color: Colors.amber,
              child: Text(
                "Header",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
                textAlign: TextAlign.center,
              ),
            ),
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(20),
            itemBuilder: (context, index) => Card(
                elevation: 2,
                child: LayoutBuilder(builder: (context, costrains) {
                  if (variableSet == 0) {
                    height = costrains.maxHeight;
                    width = costrains.maxWidth;
                    variableSet++;
                  }
                  return GridTile(
                    key: index == 4 ? Key("12") : null,
                    child: Image.network(
                      _imageUris[index],
                      fit: BoxFit.cover,
                      height: height,
                      width: width,
                    ),
                  );
                }),
              ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) => true,
            onReorder: (oldIndex, newIndex) {
              final temp = _imageUris[oldIndex];
              _imageUris[oldIndex] = _imageUris[newIndex];
              _imageUris[newIndex] = temp;
              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果


示例 #6:DragAndDrop GridView 带有不可拖动的子项

在 itembuilder 中,只需将您的 widget 包装在 DragItem 中,并根据您的条件返回 isDraggable true 或 false。

isDropable 中,如果您传入 false,则此项目将不接受任何可拖动的子项。默认情况下,它设置为 true

import 'package:drag_and_drop_gridview/drag.dart'; // import this header

DrarItem(
    isDraggable: true, // whether draggable or not (Default true)
    isDropable: false, // whether dropable or not (Default true)
    child: ..///, //and pass the child
);

示例 #7:水平网格视图粘性页眉

要实现网格视图中的粘性页眉,只需调用此 horizontalStickyHeader 构造函数。默认情况下,allHeaderChildNonDraggable 设置为 false,使所有页眉 可拖动

onWillAcceptHeader (在接受和拒绝页眉元素的拖放时实现您的逻辑),

onReorderHeader (为元素的重新排序和重新索引实现您的逻辑)

如果您希望页眉成为 不可拖动的 元素,只需将 allHeaderChildNonDraggable 设置为 true

以及必需的参数:onWillAcceptitemBuilderHeaderonReordergridDelegateitemBuilder

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:drag_and_drop_gridview/drag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",


    "https://images.pexels.com/photos/443446/pexels-photo-443446.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/2113566/pexels-photo-2113566.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/3244513/pexels-photo-3244513.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1438761/pexels-photo-1438761.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/2835562/pexels-photo-2835562.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/2440021/pexels-photo-2440021.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/572897/pexels-photo-572897.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
  ];

  int variableSet = 0, variableSetHeader = 0;
  ScrollController _scrollController;
  double width;
  double height;
  double widthHeader;
  double heightHeader;
  List<String> listOfHeader = ["1", "2", "3", "4", "5"];

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('DragAndDropGridView'),
        ),
        body: Center(
          child: DragAndDropGridView.horizontalStickyHeader(
            itemBuilderHeader: (context, pos) => Card(
              elevation: 2,
              child: LayoutBuilder(builder: (context, costrains) {
                if (variableSet == 0) {
                  heightHeader = costrains.maxHeight;
                  widthHeader = costrains.maxWidth;
                  variableSetHeader++;
                }
                return Container(
                  height: heightHeader,
                  width: widthHeader,
                  alignment: Alignment.center,
                  child: Text(
                    "${listOfHeader[pos]}",
                    textAlign: TextAlign.center,
                  ),
                );
              }),
            ),
            headerItemCount: 5,
            headerPadding: EdgeInsets.all(10),
            headerGridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 5,
              childAspectRatio: 2.8,
            ),
            onReorderHeader: (oldIndex, newIndex) {
              var temp = listOfHeader[oldIndex];
              listOfHeader[oldIndex] = listOfHeader[newIndex];
              listOfHeader[newIndex] = temp;
              setState(() {});
            },
            onWillAcceptHeader: (oldIndex, newIndex) {
              return true;
            },
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 5,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(20),
            itemBuilder: (context, index) => DragItem(
              child: Card(
                elevation: 2,
                child: LayoutBuilder(builder: (context, costrains) {
                  if (variableSet == 0) {
                    height = costrains.maxHeight;
                    width = costrains.maxWidth;
                    variableSet++;
                  }
                  return GridTile(
                    key: index == 4 ? Key("12") : null,
                    child: Image.network(
                      _imageUris[index],
                      fit: BoxFit.cover,
                      height: height,
                      width: width,
                    ),
                  );
                }),
              ),
            ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) => true,
            onReorder: (oldIndex, newIndex) {
              int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
              int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);

              if (indexOfFirstItem > indexOfSecondItem) {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i > _imageUris.indexOf(_imageUris[newIndex]);
                    i--) {
                  var tmp = _imageUris[i - 1];
                  _imageUris[i - 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              } else {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i < _imageUris.indexOf(_imageUris[newIndex]);
                    i++) {
                  var tmp = _imageUris[i + 1];
                  _imageUris[i + 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              }
              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果


示例 #8:垂直网格视图粘性页眉

要实现网格视图中的粘性页眉,只需调用此 stickyHeader 构造函数。

默认情况下,allHeaderChildNonDraggable 设置为 false,使所有页眉 可拖动

onWillAcceptHeader (在接受和拒绝页眉元素的拖放时实现您的逻辑),

onReorderHeader (为元素的重新排序和重新索引实现您的逻辑)

如果您希望页眉成为 不可拖动的 元素,只需将 allHeaderChildNonDraggable 设置为 true

以及必需的参数:onWillAcceptitemBuilderHeaderonReordergridDelegateitemBuilder

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:drag_and_drop_gridview/drag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';

import 'package:flutter/services.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _imageUris = [
    "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
    "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
    "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
  ];

  int variableSet = 0, variableSetHeader = 0;
  ScrollController _scrollController;
  double width;
  double height;
  double widthHeader;
  double heightHeader;
  List<String> listOfHeader = ["1", "2"];

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('DragAndDropGridView'),
        ),
        body: Center(
          child: DragAndDropGridView.stickyHeader(
            itemBuilderHeader: (context, pos) => Card(
              elevation: 2,
              child: LayoutBuilder(builder: (context, costrains) {
                if (variableSet == 0) {
                  heightHeader = costrains.maxHeight;
                  widthHeader = costrains.maxWidth;
                  variableSetHeader++;
                }
                return Container(
                  height: heightHeader,
                  width: widthHeader,
                  alignment: Alignment.center,
                  child: Text(
                    "${listOfHeader[pos]}",
                    textAlign: TextAlign.center,
                  ),
                );
              }),
            ),
            headerItemCount: 2,
            headerPadding: EdgeInsets.all(10),
            headerGridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 2.8,
            ),
            onReorderHeader: (oldIndex, newIndex) {
              var temp = listOfHeader[oldIndex];
              listOfHeader[oldIndex] = listOfHeader[newIndex];
              listOfHeader[newIndex] = temp;
              setState(() {});
            },
            onWillAcceptHeader: (oldIndex, newIndex) {
              return true;
            },
            controller: _scrollController,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              childAspectRatio: 3 / 4.5,
            ),
            padding: EdgeInsets.all(10),
            itemBuilder: (context, index) => Card(
              elevation: 2,
              child: LayoutBuilder(builder: (context, costrains) {
                if (variableSet == 0) {
                  height = costrains.maxHeight;
                  width = costrains.maxWidth;
                  variableSet++;
                }
                return GridTile(
                  key: index == 4 ? Key("12") : null,
                  child: Image.network(
                    _imageUris[index],
                    fit: BoxFit.cover,
                    height: height,
                    width: width,
                  ),
                );
              }),
            ),
            itemCount: _imageUris.length,
            onWillAccept: (oldIndex, newIndex) => true,
            onReorder: (oldIndex, newIndex) {
              int indexOfFirstItem = _imageUris.indexOf(_imageUris[oldIndex]);
              int indexOfSecondItem = _imageUris.indexOf(_imageUris[newIndex]);

              if (indexOfFirstItem > indexOfSecondItem) {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i > _imageUris.indexOf(_imageUris[newIndex]);
                    i--) {
                  var tmp = _imageUris[i - 1];
                  _imageUris[i - 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              } else {
                for (int i = _imageUris.indexOf(_imageUris[oldIndex]);
                    i < _imageUris.indexOf(_imageUris[newIndex]);
                    i++) {
                  var tmp = _imageUris[i + 1];
                  _imageUris[i + 1] = _imageUris[i];
                  _imageUris[i] = tmp;
                }
              }
              setState(() {});
            },
          ),
        ),
      ),
    );
  }
}

结果


示例 #9:DragAndDropGridView 更改子项

您可以通过将 isCustomChildWhenDragging 设置为 true 并将您的子项返回到此参数 childWhenDragging 来更改子项。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
 
import 'package:flutter/services.dart';
 
void main() {
 runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
 @override
 _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 List<String> _imageUris = [
   "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
   "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
 ];
 
 int variableSet = 0;
 ScrollController _scrollController;
 double width;
 double height;
 
 @override
 void initState() {
   super.initState();
 }
 
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: Scaffold(
       appBar: AppBar(
         title: const Text('DragAndDropGridView'),
       ),
       body: Center(
         child: DragAndDropGridView(
           controller: _scrollController,
           gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
             crossAxisCount: 2,
             childAspectRatio: 3 / 4.5,
           ),
           padding: EdgeInsets.all(20),
           itemBuilder: (context, index) => Card(
             elevation: 2,
             child: LayoutBuilder(builder: (context, costrains) {
               if (variableSet == 0) {
                 height = costrains.maxHeight;
                 width = costrains.maxWidth;
                 variableSet++;
               }
               return GridTile(
                 child: Image.network(
                   _imageUris[index],
                   height: height,
                   width: width,
                 ),
               );
             }),
           ),
           isCustomChildWhenDragging: true,
           childWhenDragging: (pos) => Image.asset(
             "gifs/draganddropbg.jpg",
             height: height,
             width: width,
           ),
           itemCount: _imageUris.length,
           onWillAccept: (oldIndex, newIndex) => true,
           onReorder: (oldIndex, newIndex) {
             final temp = _imageUris[oldIndex];
             _imageUris[oldIndex] = _imageUris[newIndex];
             _imageUris[newIndex] = temp;
 
             setState(() {});
           },
         ),
       ),
     ),
   );
 }
}

结果


示例 #10:DragAndDropGridView 更改反馈

您可以通过将 isCustomFeedback 设置为 true 并将您的子项返回到此参数 feedback 来更改子项。

import 'package:drag_and_drop_gridview/devdrag.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
 
import 'package:flutter/services.dart';
 
void main() {
 runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
 @override
 _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 List<String> _imageUris = [
   "https://images.pexels.com/photos/4466054/pexels-photo-4466054.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
   "https://images.pexels.com/photos/4561739/pexels-photo-4561739.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4507967/pexels-photo-4507967.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/4321194/pexels-photo-4321194.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1053924/pexels-photo-1053924.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
   "https://images.pexels.com/photos/1624438/pexels-photo-1624438.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/1144687/pexels-photo-1144687.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
   "https://images.pexels.com/photos/2589010/pexels-photo-2589010.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260"
 ];
 
 int variableSet = 0;
 ScrollController _scrollController;
 double width;
 double height;
 
 @override
 void initState() {
   super.initState();
 }
 
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     home: Scaffold(
       appBar: AppBar(
         title: const Text('DragAndDropGridView'),
       ),
       body: Center(
         child: DragAndDropGridView(
           controller: _scrollController,
           gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
             crossAxisCount: 2,
             childAspectRatio: 3 / 4.5,
           ),
           padding: EdgeInsets.all(20),
           itemBuilder: (context, index) => Card(
             elevation: 2,
             child: LayoutBuilder(builder: (context, costrains) {
               if (variableSet == 0) {
                 height = costrains.maxHeight;
                 width = costrains.maxWidth;
                 variableSet++;
               }
               return GridTile(
                 child: Image.network(
                   _imageUris[index],
                   height: height,
                   width: width,
                 ),
               );
             }),
           ),
           isCustomFeedback: true,
           feedback: (pos) => Image.asset(
             "gifs/draganddropbg.jpg",
             height: height,
             width: width,
           ),
           itemCount: _imageUris.length,
           onWillAccept: (oldIndex, newIndex) => true,
           onReorder: (oldIndex, newIndex) {
             final temp = _imageUris[oldIndex];
             _imageUris[oldIndex] = _imageUris[newIndex];
             _imageUris[newIndex] = temp;
 
             setState(() {});
           },
         ),
       ),
     ),
   );
 }
}

结果

支持

您还可以通过购买咖啡来支持我们。您的支持不胜感激。 ?

Buy Me A Coffee

GitHub

查看 Github