flutter中用GridView擼出可拖拽,刪除,上傳等圖片操作


import 'package:flutter/material.dart';
import 'package:n9a_crm/widgets/tip/tip.dart';

class ProductImg extends StatefulWidget {
  @override
  _ProductImgState createState() => _ProductImgState();
}

class _ProductImgState extends State<ProductImg> {
  var _imgs = [
    "http://img5.mtime.cn/mg/2020/04/02/100052.90885849.jpg",
    "http://img5.mtime.cn/mg/2020/03/30/104612.95383214.jpg",
    "http://img5.mtime.cn/mg/2020/04/07/092906.73796826.jpg",
    "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fn.sinaimg.cn%2Fsinacn12%2F0%2Fw640h960%2F20180426%2F356f-fzrwiay9756380.jpg&refer=http%3A%2F%2Fn.sinaimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1619680186&t=6098cb2d8c6588bdbc7d2b4f27e6f133"
  ];
  String _movingValue; // 記錄正在移動的數據

  _deleImg(String value) {
    setState(() {
      this._imgs.remove(value);
    });
  }

  // 生成GridView的items
  List<Widget> buildItems() {
    List<Widget> items = List<Widget>();
    _imgs.forEach((value) {
      items.add(draggableItem(value));
    });
    items.add(UpBtn(imgList: _imgs));
    return items;
  }

  // 生成可拖動的item
  Widget draggableItem(value) {
    return Draggable(
      data: value,
      child: DragTarget(
        builder: (context, candidateData, rejectedData) {
          return baseItem(value);
        },
        onWillAccept: (moveData) {
          print('=== onWillAccept: $moveData ==> $value');

          var accept = moveData != null;
          if (accept) {
            exchangeItem(moveData, value, false);
          }
          return accept;
        },
        onAccept: (moveData) {
          print('=== onAccept: $moveData ==> $value');
          exchangeItem(moveData, value, true);
        },
        onLeave: (moveData) {
          print('=== onLeave: $moveData ==> $value');
        },
      ),
      feedback: Container(
          width: 110,
          height: 110,
          child: ClipRRect(
              borderRadius: BorderRadius.all(Radius.circular(5)),
              child: Image.network(
                value,
                fit: BoxFit.cover,
              ))),
      childWhenDragging: null,
      onDragStarted: () {
        print('=== onDragStarted');
        setState(() {
          _movingValue = value; //記錄開始拖拽的數據
        });
      },
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        print('=== onDraggableCanceled');
        setState(() {
          _movingValue = null; //清空標記進行重繪
        });
      },
      onDragCompleted: () {
        print('=== onDragCompleted');
      },
    );
  }

  // 基礎展示的item 此處設置width,height對GridView 無效,主要是偷懶給feedback用
  Widget baseItem(value, [bgColor]) {
    if (value == _movingValue) {
      return Container();
    }
    return Stack(
      children: [
        Container(
            width: double.infinity,
            height: double.infinity,
            color: bgColor,
            child: ClipRRect(
                borderRadius: BorderRadius.all(Radius.circular(5)),
                child: Image.network(
                  value,
                  fit: BoxFit.cover,
                ))),
        Positioned(
          child: GestureDetector(
            onTap: () => _deleImg(value),
            behavior: HitTestBehavior.translucent,
            child: Image.asset('assets/product/close.png'),
          ),
          top: 0,
          right: 0,
        )
      ],
    );
  }

  // 重新排序
  void exchangeItem(moveData, toData, onAccept) {
    setState(() {
      var toIndex = _imgs.indexOf(toData);

      _imgs.remove(moveData);
      _imgs.insert(toIndex, moveData);

      if (onAccept) {
        _movingValue = null;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          alignment: Alignment.centerLeft,
          margin: EdgeInsets.only(left: 15, top: 10, bottom: 10),
          child: Text(
            '產品圖片',
            style: TextStyle(color: Color(0xff888888), fontSize: 15),
          ),
        ),
        Tip(text: '支持 jpg、png格式,拖動圖片重新排序,默認第一張圖片為主圖,建議每張上傳文件大小200K以內'),
        Container(
          margin: EdgeInsets.only(
            top: 15,
            left: 15,
            right: 15,
          ),
          child: GridView(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, mainAxisSpacing: 15, crossAxisSpacing: 15, childAspectRatio: 1),
            children: buildItems(),
            shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(), //禁止滾動
          ),
        ),
      ],
    );
  }
}

//添加圖片
class UpBtn extends StatefulWidget {
  final imgList;
  UpBtn({Key key, this.imgList}) : super(key: key);
  @override
  _UpBtnState createState() => _UpBtnState();
}

class _UpBtnState extends State<UpBtn> {
  //選擇相冊照片
  Future getImage() async {
    var imageUrl = await ImagePicker().getImage(source: ImageSource.gallery);
    setState(() {
      widget.imgList.add(imageUrl);
    });
    print(widget.imgList);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: getImage,
      child: Container(
        decoration: BoxDecoration(
          color: Color(0xfff7f7f7),
          borderRadius: BorderRadius.all(Radius.circular(5)),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              margin: EdgeInsets.only(bottom: 5),
              child: Image.asset(
                'assets/product/addimg.png',
              ),
            ),
            Text('添加圖片', style: TextStyle(fontSize: 13, color: Color(0xff888888)))
          ],
        ),
      ),
    );
  }
}
//效果如下,可拖動,拿走不謝

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM