Closed meomap closed 2 years ago
Hi @meomap Thank you for opening the issue. I will try to fix that problem
I am wondering why that problem is happening. Could you share the code snippet of the part where you use ReorderableBuilder
? Are you changing some values of ReorderableBuilder
while dragging? @meomap
Sure, we use ReorderableBuilder
to render a grid view of photo collection where user can add new photo, remove existing one and dragging to change order.
Here is code snippet:
import 'package:flutter/material.dart';
import 'package:equatable/equatable.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart';
import 'package:flutter_reorderable_grid_view/widgets/widgets.dart';
class PhotoCollectionModal extends StatefulWidget {
const PhotoCollectionModal({Key? key}) : super(key: key);
@override
State<PhotoCollectionModal> createState() => _PhotoCollectionModalState();
}
class _PhotoCollectionModalState extends State<PhotoCollectionModal> {
bool draggingItem = false;
final _gridViewKey = GlobalKey();
final _scrollController = ScrollController();
final List<Photo> items =
List<Photo>.generate(10, (index) => _dummyPhoto(index));
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
const double space = 16;
const cols = 3;
final generatedChildren = List<Widget>.generate(
items.length,
(index) => Container(
key: ValueKey(items[index]),
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: BorderRadius.circular(4),
border: Border.all(color: colorScheme.outline),
),
child: Stack(
children: [
Center(
child: CachedNetworkImage(
imageUrl: items[index].networkUrl,
fit: BoxFit.scaleDown,
),
),
Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.all(4),
child: GestureDetector(
onTap: () => handleRemove(index),
child:
Icon(Icons.remove_circle, color: colorScheme.error)),
))
],
),
));
return SafeArea(
child: Scaffold(
appBar: AppBar(title: const Text('Collection')),
floatingActionButton: draggingItem
? null
: FloatingActionButton(
child: const Icon(Icons.add), onPressed: handleAdd),
body: Padding(
padding: const EdgeInsets.all(space),
child: ReorderableBuilder(
children: generatedChildren,
onReorder: handleReorder,
enableLongPress: false,
dragChildBoxDecoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.secondaryContainer
.withOpacity(0.54)),
onDragStarted: () {
setState(() {
draggingItem = true;
});
},
onDragEnd: () {
setState(() {
draggingItem = false;
});
},
scrollController: _scrollController,
builder: (children) {
return GridView.builder(
key: _gridViewKey,
controller: _scrollController,
itemCount: children.length,
itemBuilder: (context, index) {
return children[index];
},
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: cols,
mainAxisSpacing: space,
crossAxisSpacing: space,
),
);
},
),
)),
);
}
void handleAdd() {
setState(() {
items.add(_dummyPhoto(items.length));
});
}
void handleRemove(int index) {
setState(() {
items.removeAt(index);
});
}
void handleReorder(List<OrderUpdateEntity> updates) {
for (final entry in updates) {
if (entry.oldIndex >= items.length || entry.newIndex >= items.length) {
// Skip deleted one
continue;
}
final child = items.removeAt(entry.oldIndex);
items.insert(entry.newIndex, child);
}
if (!mounted) return;
setState(() {});
}
}
Photo _dummyPhoto(int index) => Photo(
'https://picsum.photos/${100 + index}/${100 + index}/',
DateTime.now().microsecondsSinceEpoch + index);
class Photo extends Equatable {
final int id;
final String networkUrl;
const Photo(this.networkUrl, this.id);
@override
List<Object?> get props => [networkUrl, id];
}
In void handleReorder(List<OrderUpdateEntity> updates)
, we noticed that when user removed an item then immediately drag one at the end of list, entry.oldIndex
sometimes equals current items.length
. It happens occasionally and is reproducible in dev environment.
I realized that this bug that you describe seems to happen when using GridView.builder
. I also recognized that the animation of removing an item is not working.
So if you don't have a special reason to use GridView.builder
, you could also use GridView
as workaround. I will try to fix this problem in the next days. @meomap
return GridView(
key: _gridViewKey,
controller: _scrollController,
children: children,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: cols,
mainAxisSpacing: space,
crossAxisSpacing: space,
),
I think I found a solution, so you could also wait for the update in the next days 👍 @meomap
@karvulf It's ok, I think it's just a minor glitch and we don't have much users affected by it yet. I can use GridView
as well. No need to hurry :)
Thank you so much for your support 👌
The bug should be fixed and released in a few minutes.
You can use version 3.1.3
for that. Also the animation for adding or removing your images should work now :)
I am closing this issue, if there are some other new issues with this update, feel free to open a new one @meomap
That's great! @karvulf Thanks so much 👌
Hello, thank you for your great package.
We've got this exception thrown at the production app.
Sentry stacktrace: