flutter 抖动:可拖动项到达屏幕底部时向下滚动

e37o9pze  于 2023-01-02  发布在  Flutter
关注(0)|答案(1)|浏览(195)

我正在尝试使用GridView.custom创建一个拖放操作。我希望发生的是,当拖动一个项目时,如果它到达屏幕的顶部或底部,网格视图就会滚动。是否有一种内置的方法可以做到这一点,或者是否有一种必须实现的解决方案。在本例中,我使用flutter_staggered_grid_view包。

GridView.custom(
      shrinkWrap: true,
      primary: false,
      scrollDirection: Axis.vertical,
      gridDelegate: SliverQuiltedGridDelegate(
        crossAxisCount: 4,
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
        repeatPattern: QuiltedGridRepeatPattern.inverted,
        pattern: widget.pattern,
      ),
      childrenDelegate: SliverChildBuilderDelegate(
        childCount: widget.children.length,
        (context, index) {
          var selectedWidget = widget.children[index];
          LongPressDraggable<GlobalKey>(
                  data: selectedWidget.key,
                  onDragStarted: _onDragStarted,
                  onDragEnd: _onDragEnd,
                  feedback:
                      SizedBox(width: 100, height: 100, child: selectedWidget),
                  childWhenDragging: Container(),
                  child: DragTarget<GlobalKey>(
                    builder: (context, accepted, rejected) => selectedWidget,
                    onWillAccept: (GlobalKey? accept) {
                      return true;
                    },
                    onAccept: (GlobalKey item) {
                      int startIndex =
                          widget.children.indexWhere((x) => x.key == item);
                      int endIndex = widget.children
                          .indexWhere((x) => x.key == selectedWidget.key);
                      widget.onReorder(startIndex, endIndex);
                    },
                  ),
                )
              },
            ),
           );
rsaldnfx

rsaldnfx1#

比较GridView区域中Y轴的Draggable位置。
这是样品如果Draggle位于高度为20的顶部区域,则向上滚动;如果Draggle位于高度为20的底部区域,则向下滚动。

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  final List<int> droppedIndexList = [];
  late final ScrollController scrollController;

  final GlobalKey gridViewKey = GlobalKey();

  void initState() {
    super.initState();
    scrollController = ScrollController();
    Timer.periodic(const Duration(milliseconds: 100), (_) {
      if(scrollDirection == 0) {
        return;
      } else if(scrollDirection == 1) { // scroll down
        scrollController.animateTo(
          min(scrollController.offset + 20, scrollController.position.maxScrollExtent),
          duration: const Duration(milliseconds: 100),
          curve: Curves.linear,
        );
      } else if(scrollDirection == -1) { // scroll up
        scrollController.animateTo(
          max(scrollController.offset - 20, scrollController.position.minScrollExtent),
          duration: const Duration(milliseconds: 100),
          curve: Curves.linear,
        );
      }
    });
  }

  int scrollDirection = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 100),
          child: SizedBox(
            width: 600,
            child: Column(

              children: [
                SizedBox(
                  height: 200,
                  child: Center(
                    child: Draggable(
                      onDragUpdate: (details) {
                        final s = gridViewKey.currentContext!.size!;
                        final p = (gridViewKey.currentContext!.findRenderObject() as RenderBox).globalToLocal(details.globalPosition);

                        print(p.dy);

                        if(0 <= p.dy && p.dy <= 20) {
                          scrollDirection = -1;
                        } else if(s.height - 20 <= p.dy && p.dy <= s.height) {
                          scrollDirection = 1;
                        } else {
                          scrollDirection = 0;
                        }
                      },
                      data: Colors.black,
                      feedback: Container(
                        width: 100,
                        height: 100,
                        color: Colors.black,
                      ),
                      child: Container(
                        width: 100,
                        height: 100,
                        color: Colors.black,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: GridView.builder(
                    key: gridViewKey,
                    controller: scrollController,
                    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 3,
                    ),
                    itemCount: 300,
                    itemBuilder: (context, index) {
                      return DragTarget<Color>(
                        onAccept: (color) {
                          setState(() {
                            droppedIndexList.add(index);
                          });
                        },
                        builder: (BuildContext context, List<Color?> candidateData, List<dynamic> rejectedData) {

                          return Container(
                            width: 200,
                            height: 200,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                                width: 1,
                              ),
                              color: droppedIndexList.contains(index) ? Colors.black : Colors.transparent,
                            ),
                            child: Center(
                              child: Text(
                                  "$index"
                              ),
                            ),
                          );
                        },
                      );
                    }
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

相关问题