当 Draggable 子项的状态发生变化时,如何更新 DragTarget?

时间:2021-06-01 22:06:02

标签: flutter flutter-bloc

我有一个列表,其中包含许多 Draggables 和 DragTargets 小部件。当 Draggable 小部件的状态发生变化时,我想更改 DragTargets 的颜色。

  1. 最初,所有 DragTargets 小部件的颜色应为灰色,但当按下可拖动小部件时,它们应变为绿色。
  2. 拖动操作完成或取消后,所有 DragTargets 小部件的颜色应再次变为灰色。

我正在尝试使用 flutter_bloc 来实现它,但出现以下错误:Error: Could not find the correct Provider<MyBloc> above this _InheritedProviderScope<MyBloc> Widget

这是一个最小的例子:

  • ListItemBloc(MyBloc)
class ListItemBloc extends Bloc<ListItemEvent, ListItemState> {
  ListItemBloc() : super(ListItemInitial());

  @override
  Stream<ListItemState> mapEventToState(
    ListItemEvent event,
  ) async* {
    if (event is OnDragStarted) {
      yield ListItemUpdated(true, false, false);
    } else if (event is OnDragCompleted) {
      yield ListItemUpdated(false, true, false);
    } else if (event is OnDraggableCanceled) {
      yield ListItemUpdated(false, false, true);
    }
  }
}
  • ListItemState
abstract class ListItemState extends Equatable {
  @override
  List<Object?> get props => [];
}

class ListItemInitial extends ListItemState {}

class ListItemUpdated extends ListItemState {
  final bool isOnDragStarted;
  final bool isOnDragCompleted;
  final bool isOnDraggableCanceled;

  ListItemUpdated(
    this.isOnDragStarted,
    this.isOnDragCompleted,
    this.isOnDraggableCanceled,
  );

  @override
  List<Object?> get props => [
        isOnDragStarted,
        isOnDragCompleted,
        isOnDraggableCanceled,
      ];
}
  • ListItemEvent
abstract class ListItemEvent extends Equatable {
  @override
  List<Object?> get props => [];
}

class OnDragStarted extends ListItemEvent {}

class OnDragCompleted extends ListItemEvent {}

class OnDraggableCanceled extends ListItemEvent {}
  • 视觉
...

List<String> folders = ['folderA', 'folderB'];

List<String> images = [
  'https://images.unsplash.com/photo-1622495805731-eefd22e836f4?ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60',
  'https://images.unsplash.com/photo-1622472263439-28f6e98d05b7?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw0fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60',
  'https://images.unsplash.com/photo-1622497274862-2dd4cd0ddaac?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw1fHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60',
  'https://images.unsplash.com/photo-1622506614848-65988f1f6b33?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyfHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60',
];

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  ...

  @override
  Widget build(BuildContext context) {
    final _length = folders.length + images.length;

    return BlocProvider<ListItemBloc>(
      create: (context) => context.read<ListItemBloc>(),
      child: MaterialApp(
        ...
        home: ListView.builder(
          itemCount: _length,
          itemBuilder: (context, index) {
            if (index < folders.length) {
              return MyDragTargetCard(folderName: folders[index]);
            }

            return MyDraggableCard(
              index: index - 2,
              imageUrl: images[index - 2],
            );
          },
        ),
      ),
    );
  }
}
class MyDraggableCard extends StatelessWidget {
  final int index;
  final String imageUrl;

  ...

  @override
  Widget build(BuildContext context) {
    print(context.read<ListItemBloc>().state); // error while trying to know the current state
    final GlobalKey _draggableKey = GlobalKey();

    Image _image = Image.network(imageUrl);

    return Draggable<Image>(
      dragAnchorStrategy: pointerDragAnchorStrategy,
      data: Image.network(imageUrl),
      feedback: DraggingCard(
        key: Key('_draggingCard$index'),
        dragKey: _draggableKey,
        image: _image,
      ),
      child: Card(
        ...
        child: _image,
      ),
      onDragStarted: () => print('onDragStarted'),
      onDragCompleted: () => print('onDragCompleted'),
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        print('onDraggableCanceled');
      },
    );
  }
}
class DraggingCard extends StatelessWidget {
  final GlobalKey dragKey;
  final Image image;

  ...

  @override
  Widget build(BuildContext context) {
    final GlobalKey _draggableKey = GlobalKey();

    return FractionalTranslation(
      translation: const Offset(-0.5, -0.5),
      child: ClipRRect(
        key: _draggableKey,
        ...
        child: SizedBox(
          height: 150,
          width: 150,
          child: Opacity(
            opacity: 0.85,
            child: image,
          ),
        ),
      ),
    );
  }
}
class _MyDragTargetCardState extends State<MyDragTargetCard> {
  late Color _folderColor;

  @override
  void initState() {
    _folderColor = Colors.grey;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print(context.read<ListItemBloc>().state); // error while trying to know the current state
    return DragTarget<Image>(
      builder: (context, candidateData, rejectedData) {
        return Card(
          color: _folderColor,
          child: Center(child: Text(widget.folderName)),
        );
      },
      onWillAccept: (item) => true,
      onAccept: (item) => print('onAccept'),
      onLeave: (item) => setState(() {
        _folderColor = Colors.green;
      }),
      onMove: (item) => setState(() {
        _folderColor = Colors.red;
      }),
    );
  }
}

关于如何在不出现上述错误的情况下获取集团当前状态的任何建议?

0 个答案:

没有答案