From 205f90010c8522c4a9c566a16011c739fe0e7551 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Sun, 27 Oct 2024 15:24:29 -0500 Subject: [PATCH 01/15] Now can do some dragging but doesn't work perfectly --- .../asset_picker_builder_delegate.dart | 387 +++++++++++++++--- 1 file changed, 320 insertions(+), 67 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index cff1802c..24fd9350 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -14,6 +14,7 @@ import 'package:photo_manager/photo_manager.dart'; import 'package:photo_manager_image_provider/photo_manager_image_provider.dart'; import 'package:provider/provider.dart'; import 'package:wechat_picker_library/wechat_picker_library.dart'; +import 'package:drag_select_grid_view/drag_select_grid_view.dart'; import '../constants/constants.dart'; import '../constants/enums.dart'; @@ -408,16 +409,13 @@ abstract class AssetPickerBuilderDelegate { return Align( alignment: Alignment.bottomCenter, child: Container( - width: double.infinity, + alignment: AlignmentDirectional.centerEnd, padding: const EdgeInsets.all(6), decoration: BoxDecoration( gradient: LinearGradient( begin: AlignmentDirectional.bottomCenter, end: AlignmentDirectional.topCenter, - colors: [ - theme.canvasColor.withAlpha(128), - Colors.transparent, - ], + colors: [theme.dividerColor, Colors.transparent], ), ), child: Container( @@ -431,9 +429,11 @@ abstract class AssetPickerBuilderDelegate { child: ScaleText( textDelegate.gifIndicator, style: TextStyle( - color: theme.textTheme.bodyMedium?.color, - fontSize: 12, - fontWeight: FontWeight.bold, + color: isAppleOS(context) + ? theme.textTheme.bodyMedium?.color + : theme.primaryColor, + fontSize: 13, + fontWeight: FontWeight.w500, ), semanticsLabel: semanticsTextDelegate.gifIndicator, strutStyle: const StrutStyle(forceStrutHeight: true, height: 1), @@ -1228,7 +1228,11 @@ class DefaultAssetPickerBuilderDelegate final bool gridRevert = effectiveShouldRevertGrid(context); return Selector?>( selector: (_, DefaultAssetPickerProvider p) => p.currentPath, - builder: (context, wrapper, _) { + builder: ( + BuildContext context, + PathWrapper? wrapper, + _, + ) { // First, we need the count of the assets. int totalCount = wrapper?.assetCount ?? 0; final Widget? specialItem; @@ -1269,51 +1273,49 @@ class DefaultAssetPickerBuilderDelegate final textDirection = Directionality.of(context); Widget sliverGrid(BuildContext context, List assets) { - return SliverGrid( - delegate: SliverChildBuilderDelegate( - (context, int index) { - if (gridRevert) { - if (index < placeholderCount) { - return const SizedBox.shrink(); - } - index -= placeholderCount; - } - return MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, - ), - ), - ); - }, - childCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - findChildIndexCallback: (Key? key) { - if (key is ValueKey) { - return findChildIndexBuilder( - id: key.value, + return SliverToBoxAdapter( + child: Column( + children: [ + DragSelectGridView( + itemBuilder: (BuildContext context, int index, bool selected) { + Widget c = MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, + ), + ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, assets: assets, placeholderCount: placeholderCount, - ); - } - return null; - }, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - ), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - mainAxisSpacing: itemSpacing, - crossAxisSpacing: itemSpacing, - ), + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 150, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + ), + ) + ] + ) ); } @@ -1500,7 +1502,6 @@ class DefaultAssetPickerBuilderDelegate hint += ', ${asset.title}'; } return Semantics( - key: ValueKey('${asset.id}-semantics'), button: false, enabled: !isBanned, excludeSemantics: true, @@ -1720,6 +1721,12 @@ class DefaultAssetPickerBuilderDelegate isOriginal: false, thumbnailSize: gridThumbnailSize, ); + SpecialImageType? type; + if (imageProvider.imageFileType == ImageFileType.gif) { + type = SpecialImageType.gif; + } else if (imageProvider.imageFileType == ImageFileType.heic) { + type = SpecialImageType.heic; + } return Stack( fit: StackFit.expand, children: [ @@ -1729,16 +1736,8 @@ class DefaultAssetPickerBuilderDelegate failedItemBuilder: failedItemBuilder, ), ), - FutureBuilder( - future: imageProvider.imageFileType, - builder: (context, snapshot) { - if (snapshot.data case final type? - when type == ImageFileType.gif) { - return gifIndicator(context, asset); - } - return const SizedBox.shrink(); - }, - ), + if (type == SpecialImageType.gif) // 如果为GIF则显示标识 + gifIndicator(context, asset), if (asset.type == AssetType.video) // 如果为视频则显示标识 videoIndicator(context, asset), if (asset.isLivePhoto) buildLivePhotoIndicator(context, asset), @@ -2172,6 +2171,12 @@ class DefaultAssetPickerBuilderDelegate ); } + + + + + + @override Widget selectIndicator(BuildContext context, int index, AssetEntity asset) { final double indicatorSize = @@ -2221,10 +2226,18 @@ class DefaultAssetPickerBuilderDelegate ), ); if (isPreviewEnabled) { - return PositionedDirectional( - top: 0, - end: 0, - child: selectorWidget, + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + parent: this, + context: context, + asset: asset, + child: PositionedDirectional( + top: 0, + end: 0, + child: selectorWidget, + ) ); } return selectorWidget; @@ -2458,3 +2471,243 @@ class DefaultAssetPickerBuilderDelegate ); } } + + + + + + + + + + + + + + + + + + + + +class SelectableItem extends StatefulWidget { + const SelectableItem({ + Key? key, + required this.index, + required this.color, + required this.selected, + required this.child, + required this.asset, + required this.parent, + required this.context, + }) : super(key: key); + + final int index; + final MaterialColor color; + final bool selected; + final Widget child; + final AssetEntity asset; + final DefaultAssetPickerBuilderDelegate parent; + final BuildContext context; + + @override + _SelectableItemState createState() => _SelectableItemState(); +} + +class _SelectableItemState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _controller; + late final Animation _scaleAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + value: widget.selected ? 1 : 0, + duration: kThemeChangeDuration, + vsync: this, + ); + + _scaleAnimation = Tween(begin: 1, end: 0.8).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.ease, + ), + ); + } + + @override + void didUpdateWidget(SelectableItem oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.selected != widget.selected) { + if (widget.selected) { + //_controller.forward(); + } else { + //_controller.reverse(); + } + widget.parent.selectAsset(widget.context, widget.asset, widget.index, oldWidget.selected); + setState((){}); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, child) { + return Container( + child: Transform.scale( + scale: _scaleAnimation.value, + child: DecoratedBox( + child: child, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: calculateColor(), + ), + ), + ), + ); + }, + child: widget.child + ); + } + + Color? calculateColor() { + return Color.lerp( + widget.color.shade500, + widget.color.shade900, + _controller.value, + ); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class SelectableItem22 extends StatefulWidget { + const SelectableItem22({ + Key? key, + required this.index, + required this.color, + required this.selected, + }) : super(key: key); + + final int index; + final MaterialColor color; + final bool selected; + + @override + _SelectableItemState22 createState() => _SelectableItemState22(); +} + +class _SelectableItemState22 extends State + with SingleTickerProviderStateMixin { + late final AnimationController _controller; + late final Animation _scaleAnimation; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + value: widget.selected ? 1 : 0, + duration: kThemeChangeDuration, + vsync: this, + ); + + _scaleAnimation = Tween(begin: 1, end: 0.8).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.ease, + ), + ); + } + + @override + void didUpdateWidget(SelectableItem22 oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.selected != widget.selected) { + if (widget.selected) { + _controller.forward(); + } else { + _controller.reverse(); + } + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _scaleAnimation, + builder: (context, child) { + return Container( + child: Transform.scale( + scale: _scaleAnimation.value, + child: DecoratedBox( + child: child, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: calculateColor(), + ), + ), + ), + ); + }, + child: Container( + alignment: Alignment.center, + child: Text( + 'Item\n#${widget.index}', + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18, color: Colors.white), + ), + ), + ); + } + + Color? calculateColor() { + return Color.lerp( + widget.color.shade500, + widget.color.shade900, + _controller.value, + ); + } +} From a08084c207a70c2962cff16a24b2fd3da7a617ee Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Mon, 28 Oct 2024 03:28:43 -0500 Subject: [PATCH 02/15] Now is pretty much working, but not auto scroll. --- .../delegates/asset_picker_builder_delegate.dart | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 24fd9350..99913a52 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -616,6 +616,7 @@ abstract class AssetPickerBuilderDelegate { child: IconButton( onPressed: () { Navigator.maybeOf(context)?.maybePop(); + Navigator.maybeOf(context)?.maybePop(); }, tooltip: MaterialLocalizations.of(context).closeButtonTooltip, icon: Icon( @@ -641,6 +642,7 @@ abstract class AssetPickerBuilderDelegate { child: IconButton( onPressed: () { Navigator.maybeOf(context)?.maybePop(); + Navigator.maybeOf(context)?.maybePop(); }, icon: const Icon(Icons.close), padding: EdgeInsets.zero, @@ -889,6 +891,7 @@ class DefaultAssetPickerBuilderDelegate provider.selectAsset(asset); if (isSingleAssetMode && !isPreviewEnabled) { Navigator.maybeOf(context)?.maybePop(provider.selectedAssets); + Navigator.maybeOf(context)?.maybePop(provider.selectedAssets); } } @@ -1277,6 +1280,7 @@ class DefaultAssetPickerBuilderDelegate child: Column( children: [ DragSelectGridView( + autoScrollHotspotHeight: 150, itemBuilder: (BuildContext context, int index, bool selected) { Widget c = MergeSemantics( child: Directionality( @@ -1308,10 +1312,10 @@ class DefaultAssetPickerBuilderDelegate shrinkWrap: true, // Explicitly disable semantic indexes for custom usage. addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150, - crossAxisSpacing: 8, - mainAxisSpacing: 8, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, ), ) ] @@ -1679,6 +1683,7 @@ class DefaultAssetPickerBuilderDelegate onPressed: shouldAllowConfirm ? () { Navigator.maybeOf(context)?.maybePop(p.selectedAssets); + Navigator.maybeOf(context)?.maybePop(p.selectedAssets); } : null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, From 320b512a74226ef49fce6f3f6d8fccd183f3dca0 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Fri, 1 Nov 2024 03:49:43 -0500 Subject: [PATCH 03/15] Tried to see if other scroll controllers were causing the problem but didn't have much luck this way --- .../asset_picker_builder_delegate.dart | 161 +++++++++++------- 1 file changed, 100 insertions(+), 61 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 24fd9350..f67e2b96 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1276,43 +1276,49 @@ class DefaultAssetPickerBuilderDelegate return SliverToBoxAdapter( child: Column( children: [ - DragSelectGridView( - itemBuilder: (BuildContext context, int index, bool selected) { - Widget c = MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, + DragSelectHolder( + // https://stackoverflow.com/questions/52000130/flutter-get-local-position-of-gesture-detector + // https://www.google.com/search?q=geusterdetector+flutter+local+position+is+relative+to+grid+not+screen&oq=geusterdetector+flutter+local+position+is+relative+to+grid+not+screen&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCTE4MTIxajBqMagCALACAA&sourceid=chrome&ie=UTF-8 + dragSelectView: + DragSelectGridView( + topPadding: topPadding, + itemBuilder: (BuildContext context, int index, bool selected) { + Widget c = MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, + ), ), - ), - ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); - }, - itemCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - shrinkWrap: true, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150, - crossAxisSpacing: 8, - mainAxisSpacing: 8, - ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: 150, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + ), + ) ) ] ) @@ -1347,9 +1353,7 @@ class DefaultAssetPickerBuilderDelegate return Directionality( textDirection: effectiveGridDirection(context), - child: ColoredBox( - color: theme.canvasColor, - child: Selector>( + child: Selector>( selector: (_, DefaultAssetPickerProvider p) => p.currentAssets, builder: (BuildContext context, List assets, _) { @@ -1357,30 +1361,12 @@ class DefaultAssetPickerBuilderDelegate context.bottomPadding + bottomSectionHeight, ); appBarPreferredSize ??= appBar(context).preferredSize; - return CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: gridScrollController, - anchor: gridRevert ? anchor : 0, - center: gridRevert ? gridRevertKey : null, - slivers: [ - if (isAppleOS(context)) - SliverGap.v( - context.topPadding + appBarPreferredSize!.height, - ), - sliverGrid(context, assets), - // Ignore the gap when the [anchor] is not equal to 1. - if (gridRevert && anchor == 1) bottomGap, - if (gridRevert) - SliverToBoxAdapter( - key: gridRevertKey, - child: const SizedBox.shrink(), - ), - if (isAppleOS(context) && !gridRevert) bottomGap, - ], - ); + return + sliverGrid(context, assets); + /*], + );*/ }, ), - ), ); }, ); @@ -1388,6 +1374,19 @@ class DefaultAssetPickerBuilderDelegate ); } + + + + + + + + + + + + + /// There are several conditions within this builder: /// * Return item builder according to the asset's type. /// * [AssetType.audio] -> [audioItemBuilder] @@ -2491,6 +2490,46 @@ class DefaultAssetPickerBuilderDelegate + + + + + + + +class DragSelectHolder extends StatelessWidget { + DragSelectGridView dragSelectView; + + DragSelectHolder({ + required this.dragSelectView + }); + + @override + Widget build(BuildContext context) { + return /*SizedBox( + width: context.size?.width, + height: context.size?.height, + child: Scaffold( + body: + */dragSelectView; + /*) + );*/ + } +} + + + + + + + + + + + + + + class SelectableItem extends StatefulWidget { const SelectableItem({ Key? key, From 6f6a3a6bd357b2fb875b1c5142fba1cff4a418a0 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Tue, 5 Nov 2024 02:54:15 -0600 Subject: [PATCH 04/15] Drag select is working --- lib/src/delegates/asset_picker_builder_delegate.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 99913a52..5f35abaa 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1280,6 +1280,7 @@ class DefaultAssetPickerBuilderDelegate child: Column( children: [ DragSelectGridView( + gridScrollController: gridScrollController, autoScrollHotspotHeight: 150, itemBuilder: (BuildContext context, int index, bool selected) { Widget c = MergeSemantics( From ce96cb32027f3496e13c27f14167c3c7d46d9f7c Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Tue, 5 Nov 2024 03:05:58 -0600 Subject: [PATCH 05/15] Drag select is working --- .../asset_picker_builder_delegate.dart | 109 +++++------------- 1 file changed, 30 insertions(+), 79 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 6170a3ce..5f35abaa 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -616,6 +616,7 @@ abstract class AssetPickerBuilderDelegate { child: IconButton( onPressed: () { Navigator.maybeOf(context)?.maybePop(); + Navigator.maybeOf(context)?.maybePop(); }, tooltip: MaterialLocalizations.of(context).closeButtonTooltip, icon: Icon( @@ -641,6 +642,7 @@ abstract class AssetPickerBuilderDelegate { child: IconButton( onPressed: () { Navigator.maybeOf(context)?.maybePop(); + Navigator.maybeOf(context)?.maybePop(); }, icon: const Icon(Icons.close), padding: EdgeInsets.zero, @@ -889,6 +891,7 @@ class DefaultAssetPickerBuilderDelegate provider.selectAsset(asset); if (isSingleAssetMode && !isPreviewEnabled) { Navigator.maybeOf(context)?.maybePop(provider.selectedAssets); + Navigator.maybeOf(context)?.maybePop(provider.selectedAssets); } } @@ -1276,7 +1279,6 @@ class DefaultAssetPickerBuilderDelegate return SliverToBoxAdapter( child: Column( children: [ -<<<<<<< HEAD DragSelectGridView( gridScrollController: gridScrollController, autoScrollHotspotHeight: 150, @@ -1289,50 +1291,33 @@ class DefaultAssetPickerBuilderDelegate index, assets, specialItem: specialItem, -======= - DragSelectHolder( - // https://stackoverflow.com/questions/52000130/flutter-get-local-position-of-gesture-detector - // https://www.google.com/search?q=geusterdetector+flutter+local+position+is+relative+to+grid+not+screen&oq=geusterdetector+flutter+local+position+is+relative+to+grid+not+screen&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCTE4MTIxajBqMagCALACAA&sourceid=chrome&ie=UTF-8 - dragSelectView: - DragSelectGridView( - itemBuilder: (BuildContext context, int index, bool selected) { - Widget c = MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, - ), ->>>>>>> refs/remotes/origin/main ), - ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); - }, - itemCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - shrinkWrap: true, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150, - crossAxisSpacing: 8, - mainAxisSpacing: 8, - ), - ) + ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, + ), ) ] ) @@ -1408,19 +1393,6 @@ class DefaultAssetPickerBuilderDelegate ); } - - - - - - - - - - - - - /// There are several conditions within this builder: /// * Return item builder according to the asset's type. /// * [AssetType.audio] -> [audioItemBuilder] @@ -1712,6 +1684,7 @@ class DefaultAssetPickerBuilderDelegate onPressed: shouldAllowConfirm ? () { Navigator.maybeOf(context)?.maybePop(p.selectedAssets); + Navigator.maybeOf(context)?.maybePop(p.selectedAssets); } : null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, @@ -2513,28 +2486,6 @@ class DefaultAssetPickerBuilderDelegate -class DragSelectHolder extends StatelessWidget { - DragSelectGridView dragSelectView; - - DragSelectHolder({ - required this.dragSelectView - }); - - @override - Widget build(BuildContext context) { - return /*SizedBox( - width: context.size?.width, - height: context.size?.height, - child: Scaffold( - body: - */dragSelectView; - /*) - );*/ - } -} - - - From e261408e2c7c817b42d529de1c687f8acb5eedd3 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Tue, 5 Nov 2024 05:14:46 -0600 Subject: [PATCH 06/15] Moving toward it working, but more elegant --- .../delegates/asset_picker_builder_delegate.dart | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 5f35abaa..319d34df 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1276,9 +1276,7 @@ class DefaultAssetPickerBuilderDelegate final textDirection = Directionality.of(context); Widget sliverGrid(BuildContext context, List assets) { - return SliverToBoxAdapter( - child: Column( - children: [ + return DragSelectGridView( gridScrollController: gridScrollController, autoScrollHotspotHeight: 150, @@ -1318,10 +1316,7 @@ class DefaultAssetPickerBuilderDelegate crossAxisSpacing: 2, mainAxisSpacing: 2, ), - ) - ] - ) - ); + ); } return LayoutBuilder( @@ -1362,7 +1357,9 @@ class DefaultAssetPickerBuilderDelegate context.bottomPadding + bottomSectionHeight, ); appBarPreferredSize ??= appBar(context).preferredSize; - return CustomScrollView( + return sliverGrid(context, assets); + + /*CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), controller: gridScrollController, anchor: gridRevert ? anchor : 0, @@ -1382,7 +1379,7 @@ class DefaultAssetPickerBuilderDelegate ), if (isAppleOS(context) && !gridRevert) bottomGap, ], - ); + );*/ }, ), ), From 1c23dcfd79d3d1689d3209e6a9292aa1cddc0bfb Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 02:34:35 -0600 Subject: [PATCH 07/15] Minimized code --- .../asset_picker_builder_delegate.dart | 50 +------------------ 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 319d34df..c21b7da5 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1276,9 +1276,7 @@ class DefaultAssetPickerBuilderDelegate final textDirection = Directionality.of(context); Widget sliverGrid(BuildContext context, List assets) { - return - DragSelectGridView( - gridScrollController: gridScrollController, + return DragSelectGridView( autoScrollHotspotHeight: 150, itemBuilder: (BuildContext context, int index, bool selected) { Widget c = MergeSemantics( @@ -2520,36 +2518,16 @@ class SelectableItem extends StatefulWidget { class _SelectableItemState extends State with SingleTickerProviderStateMixin { - late final AnimationController _controller; - late final Animation _scaleAnimation; @override void initState() { super.initState(); - - _controller = AnimationController( - value: widget.selected ? 1 : 0, - duration: kThemeChangeDuration, - vsync: this, - ); - - _scaleAnimation = Tween(begin: 1, end: 0.8).animate( - CurvedAnimation( - parent: _controller, - curve: Curves.ease, - ), - ); } @override void didUpdateWidget(SelectableItem oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.selected != widget.selected) { - if (widget.selected) { - //_controller.forward(); - } else { - //_controller.reverse(); - } widget.parent.selectAsset(widget.context, widget.asset, widget.index, oldWidget.selected); setState((){}); } @@ -2557,39 +2535,15 @@ class _SelectableItemState extends State @override void dispose() { - _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - return AnimatedBuilder( - animation: _scaleAnimation, - builder: (context, child) { - return Container( - child: Transform.scale( - scale: _scaleAnimation.value, - child: DecoratedBox( - child: child, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: calculateColor(), - ), - ), - ), - ); - }, + return Container( child: widget.child ); } - - Color? calculateColor() { - return Color.lerp( - widget.color.shade500, - widget.color.shade900, - _controller.value, - ); - } } From c8ef34b4e643d4050b8cbdcb77cb71d20119adf7 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 18:51:32 -0600 Subject: [PATCH 08/15] Drag select is documented and working --- example/lib/constants/picker_method.dart | 18 ++ example/lib/l10n/app_en.arb | 2 + example/lib/l10n/app_zh.arb | 2 + example/lib/l10n/gen/app_localizations.dart | 14 ++ .../lib/l10n/gen/app_localizations_en.dart | 9 + .../lib/l10n/gen/app_localizations_zh.dart | 8 + example/lib/pages/multi_assets_page.dart | 1 + lib/src/constants/config.dart | 4 + lib/src/constants/enums.dart | 12 ++ .../asset_picker_builder_delegate.dart | 164 +++++++++++++----- pubspec.yaml | 1 + 11 files changed, 189 insertions(+), 46 deletions(-) diff --git a/example/lib/constants/picker_method.dart b/example/lib/constants/picker_method.dart index 00857410..103ef9d4 100644 --- a/example/lib/constants/picker_method.dart +++ b/example/lib/constants/picker_method.dart @@ -329,6 +329,24 @@ class PickMethod { ); } + factory PickMethod.dragSelect(BuildContext context, int maxAssetsCount) { + return PickMethod( + icon: '📲', + name: context.l10n.pickMethodDragSelectName, + description: context.l10n.pickMethodDragSelectDescription, + method: (BuildContext context, List assets) { + return AssetPicker.pickAssets( + context, + pickerConfig: AssetPickerConfig( + maxAssets: maxAssetsCount, + selectedAssets: assets, + specialPickerType: SpecialPickerType.dragSelect, + ), + ); + }, + ); + } + factory PickMethod.keepScrollOffset({ required BuildContext context, required DefaultAssetPickerBuilderDelegate Function() delegate, diff --git a/example/lib/l10n/app_en.arb b/example/lib/l10n/app_en.arb index d40489ed..0ec38ea1 100644 --- a/example/lib/l10n/app_en.arb +++ b/example/lib/l10n/app_en.arb @@ -30,6 +30,8 @@ "pickMethodPrependItemDescription": "A special item will prepend to the assets grid.", "pickMethodNoPreviewName": "No preview", "pickMethodNoPreviewDescription": "You cannot preview assets during the picking, the behavior is like the WhatsApp/MegaTok pattern.", + "pickMethodDragSelectName": "Drag Select", + "pickMethodDragSelectDescription": "You can drag and select assets in this mode.", "pickMethodKeepScrollOffsetName": "Keep scroll offset", "pickMethodKeepScrollOffsetDescription": "Pick assets from same scroll position.", "pickMethodChangeLanguagesName": "Change Languages", diff --git a/example/lib/l10n/app_zh.arb b/example/lib/l10n/app_zh.arb index 79df1bd6..7ff4ce3d 100644 --- a/example/lib/l10n/app_zh.arb +++ b/example/lib/l10n/app_zh.arb @@ -30,6 +30,8 @@ "pickMethodPrependItemDescription": "网格的靠前位置会添加一个自定义的 widget。", "pickMethodNoPreviewName": "禁止预览", "pickMethodNoPreviewDescription": "无法预览选择的资源,与 WhatsApp/MegaTok 的行为类似。", + "pickMethodDragSelectName": "拖动选择", + "pickMethodDragSelectDescription": "您可以在此模式下拖动并选择资源。", "pickMethodKeepScrollOffsetName": "保持滚动位置", "pickMethodKeepScrollOffsetDescription": "可以从上次滚动到的位置再次开始选择。", "pickMethodChangeLanguagesName": "更改语言", diff --git a/example/lib/l10n/gen/app_localizations.dart b/example/lib/l10n/gen/app_localizations.dart index dd848222..17486c0c 100644 --- a/example/lib/l10n/gen/app_localizations.dart +++ b/example/lib/l10n/gen/app_localizations.dart @@ -8,6 +8,8 @@ import 'package:intl/intl.dart' as intl; import 'app_localizations_en.dart'; import 'app_localizations_zh.dart'; +// ignore_for_file: type=lint + /// Callers can lookup localized strings with an instance of AppLocalizations /// returned by `AppLocalizations.of(context)`. /// @@ -276,6 +278,18 @@ abstract class AppLocalizations { /// **'You cannot preview assets during the picking, the behavior is like the WhatsApp/MegaTok pattern.'** String get pickMethodNoPreviewDescription; + /// No description provided for @pickMethodDragSelectName. + /// + /// In en, this message translates to: + /// **'Drag Select'** + String get pickMethodDragSelectName; + + /// No description provided for @pickMethodDragSelectDescription. + /// + /// In en, this message translates to: + /// **'You can drag and select assets in this mode.'** + String get pickMethodDragSelectDescription; + /// No description provided for @pickMethodKeepScrollOffsetName. /// /// In en, this message translates to: diff --git a/example/lib/l10n/gen/app_localizations_en.dart b/example/lib/l10n/gen/app_localizations_en.dart index b8238fef..6392f9ba 100644 --- a/example/lib/l10n/gen/app_localizations_en.dart +++ b/example/lib/l10n/gen/app_localizations_en.dart @@ -1,5 +1,7 @@ import 'app_localizations.dart'; +// ignore_for_file: type=lint + /// The translations for English (`en`). class AppLocalizationsEn extends AppLocalizations { AppLocalizationsEn([String locale = 'en']) : super(locale); @@ -106,6 +108,13 @@ class AppLocalizationsEn extends AppLocalizations { String get pickMethodNoPreviewDescription => 'You cannot preview assets during the picking, the behavior is like the WhatsApp/MegaTok pattern.'; + @override + String get pickMethodDragSelectName => 'Drag Select'; + + @override + String get pickMethodDragSelectDescription => + 'You can drag and select assets in this mode.'; + @override String get pickMethodKeepScrollOffsetName => 'Keep scroll offset'; diff --git a/example/lib/l10n/gen/app_localizations_zh.dart b/example/lib/l10n/gen/app_localizations_zh.dart index 0d4f2e66..2da0baf9 100644 --- a/example/lib/l10n/gen/app_localizations_zh.dart +++ b/example/lib/l10n/gen/app_localizations_zh.dart @@ -1,5 +1,7 @@ import 'app_localizations.dart'; +// ignore_for_file: type=lint + /// The translations for Chinese (`zh`). class AppLocalizationsZh extends AppLocalizations { AppLocalizationsZh([String locale = 'zh']) : super(locale); @@ -100,6 +102,12 @@ class AppLocalizationsZh extends AppLocalizations { String get pickMethodNoPreviewDescription => '无法预览选择的资源,与 WhatsApp/MegaTok 的行为类似。'; + @override + String get pickMethodDragSelectName => '拖动选择'; + + @override + String get pickMethodDragSelectDescription => '您可以在此模式下拖动并选择资源。'; + @override String get pickMethodKeepScrollOffsetName => '保持滚动位置'; diff --git a/example/lib/pages/multi_assets_page.dart b/example/lib/pages/multi_assets_page.dart index 016486da..db24cb73 100644 --- a/example/lib/pages/multi_assets_page.dart +++ b/example/lib/pages/multi_assets_page.dart @@ -61,6 +61,7 @@ class _MultiAssetsPageState extends State }, ), PickMethod.noPreview(context, maxAssetsCount), + PickMethod.dragSelect(context, maxAssetsCount), PickMethod.customizableTheme(context, maxAssetsCount), PickMethod.pathNameBuilder(context, maxAssetsCount), PickMethod.customFilterOptions(context, maxAssetsCount), diff --git a/lib/src/constants/config.dart b/lib/src/constants/config.dart index 939f5fa8..a40eef33 100644 --- a/lib/src/constants/config.dart +++ b/lib/src/constants/config.dart @@ -119,12 +119,16 @@ class AssetPickerConfig { /// no more images can be selected. /// * [SpecialPickerType.noPreview] Disable preview of asset; /// Clicking on an asset selects it. + /// * [SpecialPickerType.dragSelect] User able to drag + /// and select assets. /// /// 这里包含一些特殊选择类型: /// * [SpecialPickerType.wechatMoment] 微信朋友圈模式。 /// 当用户选择了视频,将不能选择图片。 /// * [SpecialPickerType.noPreview] 禁用资源预览。 /// 多选时单击资产将直接选中,单选时选中并返回。 + /// * [SpecialPickerType.dragSelect] 用户可以拖动 + /// 并选择资产。 final SpecialPickerType? specialPickerType; /// Whether the picker should save the scroll offset between pushes and pops. diff --git a/lib/src/constants/enums.dart b/lib/src/constants/enums.dart index 686c563d..509126bd 100644 --- a/lib/src/constants/enums.dart +++ b/lib/src/constants/enums.dart @@ -25,6 +25,18 @@ enum SpecialPickerType { /// 在多选模式下无论点击选择指示还是 item 都将触发选择, /// 而在单选模式下将直接返回点击的资源。 noPreview, + + /// Drag and Select. + /// 禁用资源预览 + /// + /// There is no preview mode when clicking grid items. + /// In multiple select mode, any click (either on the select indicator or on + /// the asset itself) will select the asset. + /// In single select mode, any click directly selects the asset and returns. + /// 用户在点击网格的 item 时无法进入预览。 + /// 在多选模式下无论点击选择指示还是 item 都将触发选择, + /// 而在单选模式下将直接返回点击的资源。 + dragSelect, } /// Provide an item slot for custom widget insertion. diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index c21b7da5..f3b1469b 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -806,10 +806,12 @@ class DefaultAssetPickerBuilderDelegate /// can be selected. /// * [SpecialPickerType.noPreview] Disable preview of asset; Clicking on an /// asset selects it. + /// * [SpecialPickerType.dragSelect] User able to drag and select assets. /// /// 这里包含一些特殊选择类型: /// * [SpecialPickerType.wechatMoment] 微信朋友圈模式。当用户选择了视频,将不能选择图片。 /// * [SpecialPickerType.noPreview] 禁用资源预览。多选时单击资产将直接选中,单选时选中并返回。 + /// * [SpecialPickerType.dragSelect] 用户可以拖动并选择资产。 final SpecialPickerType? specialPickerType; /// Whether the picker should save the scroll offset between pushes and pops. @@ -835,7 +837,12 @@ class DefaultAssetPickerBuilderDelegate /// Whether the preview of assets is enabled. /// 资源的预览是否启用 - bool get isPreviewEnabled => specialPickerType != SpecialPickerType.noPreview; + bool get isPreviewEnabled => specialPickerType != SpecialPickerType.noPreview + && specialPickerType != SpecialPickerType.dragSelect; + + /// Whether the drag select is enabled. + /// 是否启用拖动选择 + bool get isDragEnabled => specialPickerType == SpecialPickerType.dragSelect; @override bool get isSingleAssetMode => provider.maxAssets == 1; @@ -1225,6 +1232,7 @@ class DefaultAssetPickerBuilderDelegate ); } + @override Widget assetsGridBuilder(BuildContext context) { appBarPreferredSize ??= appBar(context).preferredSize; @@ -1275,11 +1283,29 @@ class DefaultAssetPickerBuilderDelegate context.topPadding + appBarPreferredSize!.height; final textDirection = Directionality.of(context); - Widget sliverGrid(BuildContext context, List assets) { - return DragSelectGridView( - autoScrollHotspotHeight: 150, - itemBuilder: (BuildContext context, int index, bool selected) { - Widget c = MergeSemantics( + + Widget sliverGrid(BuildContext context, List assets, + double anchor, SliverGap bottomGap) { + return CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + controller: gridScrollController, + anchor: gridRevert ? anchor : 0, + center: gridRevert ? gridRevertKey : null, + slivers: [ + if (isAppleOS(context)) + SliverGap.v( + context.topPadding + appBarPreferredSize!.height, + ), + SliverGrid( + delegate: SliverChildBuilderDelegate( + (context, int index) { + if (gridRevert) { + if (index < placeholderCount) { + return const SizedBox.shrink(); + } + index -= placeholderCount; + } + return MergeSemantics( child: Directionality( textDirection: textDirection, child: assetGridItemBuilder( @@ -1290,31 +1316,91 @@ class DefaultAssetPickerBuilderDelegate ), ), ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); }, - itemCount: assetsGridItemCount( + childCount: assetsGridItemCount( context: context, assets: assets, placeholderCount: placeholderCount, specialItem: specialItem, ), - shrinkWrap: true, + findChildIndexCallback: (Key? key) { + if (key is ValueKey) { + return findChildIndexBuilder( + id: key.value, + assets: assets, + placeholderCount: placeholderCount, + ); + } + return null; + }, // Explicitly disable semantic indexes for custom usage. addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - crossAxisSpacing: 2, - mainAxisSpacing: 2, + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + mainAxisSpacing: itemSpacing, + crossAxisSpacing: itemSpacing, + ), + ), + // Ignore the gap when the [anchor] is not equal to 1. + if (gridRevert && anchor == 1) bottomGap, + if (gridRevert) + SliverToBoxAdapter( + key: gridRevertKey, + child: const SizedBox.shrink(), + ), + if (isAppleOS(context) && !gridRevert) bottomGap, + ], + ); + } + + Widget dragSelectGrid(BuildContext context, List assets, + double anchor, SliverGap bottomGap) { + return DragSelectGridView( + autoScrollHotspotHeight: 100, + itemBuilder: (BuildContext context, int index, bool selected) { + if (gridRevert) { + if (index < placeholderCount) { + return const SizedBox.shrink(); + } + index -= placeholderCount; + } + Widget c = MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, ), - ); + ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, + ), + ); } return LayoutBuilder( @@ -1355,39 +1441,25 @@ class DefaultAssetPickerBuilderDelegate context.bottomPadding + bottomSectionHeight, ); appBarPreferredSize ??= appBar(context).preferredSize; - return sliverGrid(context, assets); - - /*CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: gridScrollController, - anchor: gridRevert ? anchor : 0, - center: gridRevert ? gridRevertKey : null, - slivers: [ - if (isAppleOS(context)) - SliverGap.v( - context.topPadding + appBarPreferredSize!.height, - ), - sliverGrid(context, assets), - // Ignore the gap when the [anchor] is not equal to 1. - if (gridRevert && anchor == 1) bottomGap, - if (gridRevert) - SliverToBoxAdapter( - key: gridRevertKey, - child: const SizedBox.shrink(), - ), - if (isAppleOS(context) && !gridRevert) bottomGap, - ], - );*/ + if(isDragEnabled == true) + { + return dragSelectGrid(context, assets, anchor, bottomGap); + } + else + { + return sliverGrid(context, assets, anchor, bottomGap); + } }, ), ), ); }, ); - }, + } ); } + /// There are several conditions within this builder: /// * Return item builder according to the asset's type. /// * [AssetType.audio] -> [audioItemBuilder] diff --git a/pubspec.yaml b/pubspec.yaml index 4a02d12c..52c152ef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: provider: ^6.0.5 video_player: ^2.7.0 visibility_detector: ^0.4.0 + drag_select_grid_view: ^0.6.2 dev_dependencies: flutter_lints: any From ea4898cffc1a0f39b6540f46d739db52ed4df75b Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 18:53:54 -0600 Subject: [PATCH 09/15] Fixed comments on dragSelect in enum --- lib/src/constants/enums.dart | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/src/constants/enums.dart b/lib/src/constants/enums.dart index 509126bd..8d974952 100644 --- a/lib/src/constants/enums.dart +++ b/lib/src/constants/enums.dart @@ -29,13 +29,10 @@ enum SpecialPickerType { /// Drag and Select. /// 禁用资源预览 /// - /// There is no preview mode when clicking grid items. - /// In multiple select mode, any click (either on the select indicator or on - /// the asset itself) will select the asset. - /// In single select mode, any click directly selects the asset and returns. - /// 用户在点击网格的 item 时无法进入预览。 - /// 在多选模式下无论点击选择指示还是 item 都将触发选择, - /// 而在单选模式下将直接返回点击的资源。 + /// The user can drag and select items. Must be in multiple select mode. + /// Triggers all the settings of preview mode plus drag and select. + /// 用户可以拖动并选择项目。必须处于多选模式 + /// 触发预览模式的所有设置以及拖动和选择。 dragSelect, } From 9f6ce7c75c9cfae2f10807eecc848ba7ceeb7e19 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 19:13:33 -0600 Subject: [PATCH 10/15] Now fixed inconsistencies --- example/lib/constants/picker_method.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/constants/picker_method.dart b/example/lib/constants/picker_method.dart index 103ef9d4..47bb3287 100644 --- a/example/lib/constants/picker_method.dart +++ b/example/lib/constants/picker_method.dart @@ -329,7 +329,7 @@ class PickMethod { ); } - factory PickMethod.dragSelect(BuildContext context, int maxAssetsCount) { + factory PickMethod.dragSelect(BuildContext context, int maxAssetsCount) { return PickMethod( icon: '📲', name: context.l10n.pickMethodDragSelectName, From aab02debd6df4c52d49345f1588dfb065434c8cf Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 19:19:50 -0600 Subject: [PATCH 11/15] Now commited fixed and consistent delegate file --- .../asset_picker_builder_delegate.dart | 200 +++--------------- 1 file changed, 26 insertions(+), 174 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index f3b1469b..48aec69c 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -409,13 +409,16 @@ abstract class AssetPickerBuilderDelegate { return Align( alignment: Alignment.bottomCenter, child: Container( - alignment: AlignmentDirectional.centerEnd, + width: double.infinity, padding: const EdgeInsets.all(6), decoration: BoxDecoration( gradient: LinearGradient( begin: AlignmentDirectional.bottomCenter, end: AlignmentDirectional.topCenter, - colors: [theme.dividerColor, Colors.transparent], + colors: [ + theme.canvasColor.withAlpha(128), + Colors.transparent, + ], ), ), child: Container( @@ -429,11 +432,9 @@ abstract class AssetPickerBuilderDelegate { child: ScaleText( textDelegate.gifIndicator, style: TextStyle( - color: isAppleOS(context) - ? theme.textTheme.bodyMedium?.color - : theme.primaryColor, - fontSize: 13, - fontWeight: FontWeight.w500, + color: theme.textTheme.bodyMedium?.color, + fontSize: 12, + fontWeight: FontWeight.bold, ), semanticsLabel: semanticsTextDelegate.gifIndicator, strutStyle: const StrutStyle(forceStrutHeight: true, height: 1), @@ -1232,18 +1233,13 @@ class DefaultAssetPickerBuilderDelegate ); } - @override Widget assetsGridBuilder(BuildContext context) { appBarPreferredSize ??= appBar(context).preferredSize; final bool gridRevert = effectiveShouldRevertGrid(context); return Selector?>( selector: (_, DefaultAssetPickerProvider p) => p.currentPath, - builder: ( - BuildContext context, - PathWrapper? wrapper, - _, - ) { + builder: (context, wrapper, _) { // First, we need the count of the assets. int totalCount = wrapper?.assetCount ?? 0; final Widget? specialItem; @@ -1574,6 +1570,7 @@ class DefaultAssetPickerBuilderDelegate hint += ', ${asset.title}'; } return Semantics( + key: ValueKey('${asset.id}-semantics'), button: false, enabled: !isBanned, excludeSemantics: true, @@ -1751,7 +1748,6 @@ class DefaultAssetPickerBuilderDelegate onPressed: shouldAllowConfirm ? () { Navigator.maybeOf(context)?.maybePop(p.selectedAssets); - Navigator.maybeOf(context)?.maybePop(p.selectedAssets); } : null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, @@ -1809,6 +1805,16 @@ class DefaultAssetPickerBuilderDelegate failedItemBuilder: failedItemBuilder, ), ), + FutureBuilder( + future: imageProvider.imageFileType, + builder: (context, snapshot) { + if (snapshot.data case final type? + when type == ImageFileType.gif) { + return gifIndicator(context, asset); + } + return const SizedBox.shrink(); + }, + ), if (type == SpecialImageType.gif) // 如果为GIF则显示标识 gifIndicator(context, asset), if (asset.type == AssetType.video) // 如果为视频则显示标识 @@ -2244,12 +2250,6 @@ class DefaultAssetPickerBuilderDelegate ); } - - - - - - @override Widget selectIndicator(BuildContext context, int index, AssetEntity asset) { final double indicatorSize = @@ -2299,18 +2299,10 @@ class DefaultAssetPickerBuilderDelegate ), ); if (isPreviewEnabled) { - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - parent: this, - context: context, - asset: asset, - child: PositionedDirectional( - top: 0, - end: 0, - child: selectorWidget, - ) + return PositionedDirectional( + top: 0, + end: 0, + child: selectorWidget, ); } return selectorWidget; @@ -2545,25 +2537,8 @@ class DefaultAssetPickerBuilderDelegate } } - - - - - - - - - - - - - - - - - - - +/// This class is for the drag select. +/// 该类用于拖动选择。 class SelectableItem extends StatefulWidget { const SelectableItem({ Key? key, @@ -2617,126 +2592,3 @@ class _SelectableItemState extends State ); } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -class SelectableItem22 extends StatefulWidget { - const SelectableItem22({ - Key? key, - required this.index, - required this.color, - required this.selected, - }) : super(key: key); - - final int index; - final MaterialColor color; - final bool selected; - - @override - _SelectableItemState22 createState() => _SelectableItemState22(); -} - -class _SelectableItemState22 extends State - with SingleTickerProviderStateMixin { - late final AnimationController _controller; - late final Animation _scaleAnimation; - - @override - void initState() { - super.initState(); - - _controller = AnimationController( - value: widget.selected ? 1 : 0, - duration: kThemeChangeDuration, - vsync: this, - ); - - _scaleAnimation = Tween(begin: 1, end: 0.8).animate( - CurvedAnimation( - parent: _controller, - curve: Curves.ease, - ), - ); - } - - @override - void didUpdateWidget(SelectableItem22 oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.selected != widget.selected) { - if (widget.selected) { - _controller.forward(); - } else { - _controller.reverse(); - } - } - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: _scaleAnimation, - builder: (context, child) { - return Container( - child: Transform.scale( - scale: _scaleAnimation.value, - child: DecoratedBox( - child: child, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(2), - color: calculateColor(), - ), - ), - ), - ); - }, - child: Container( - alignment: Alignment.center, - child: Text( - 'Item\n#${widget.index}', - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18, color: Colors.white), - ), - ), - ); - } - - Color? calculateColor() { - return Color.lerp( - widget.color.shade500, - widget.color.shade900, - _controller.value, - ); - } -} From 2bd5fd654c1046efe1185627dcb04d5111805705 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Wed, 6 Nov 2024 20:38:27 -0600 Subject: [PATCH 12/15] Added double pop to return assets --- lib/src/delegates/asset_picker_builder_delegate.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 48aec69c..78fb5d89 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1748,6 +1748,7 @@ class DefaultAssetPickerBuilderDelegate onPressed: shouldAllowConfirm ? () { Navigator.maybeOf(context)?.maybePop(p.selectedAssets); + Navigator.maybeOf(context)?.maybePop(p.selectedAssets); } : null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, From e70eb0054fee71296d70239109f29fb475628959 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Thu, 7 Nov 2024 00:47:24 -0600 Subject: [PATCH 13/15] Added code to make it look correct on Apple phones --- .../asset_picker_builder_delegate.dart | 207 ++++++++++-------- 1 file changed, 110 insertions(+), 97 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 78fb5d89..09242060 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1281,27 +1281,70 @@ class DefaultAssetPickerBuilderDelegate final textDirection = Directionality.of(context); Widget sliverGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { - return CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: gridScrollController, - anchor: gridRevert ? anchor : 0, - center: gridRevert ? gridRevertKey : null, - slivers: [ - if (isAppleOS(context)) - SliverGap.v( - context.topPadding + appBarPreferredSize!.height, - ), - SliverGrid( - delegate: SliverChildBuilderDelegate( - (context, int index) { + double anchor, SliverGap bottomGap) { + return SliverGrid( + delegate: SliverChildBuilderDelegate( + (context, int index) { + if (gridRevert) { + if (index < placeholderCount) { + return const SizedBox.shrink(); + } + index -= placeholderCount; + } + return MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, + ), + ), + ); + }, + childCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + findChildIndexCallback: (Key? key) { + if (key is ValueKey) { + return findChildIndexBuilder( + id: key.value, + assets: assets, + placeholderCount: placeholderCount, + ); + } + return null; + }, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + mainAxisSpacing: itemSpacing, + crossAxisSpacing: itemSpacing, + ), + ); + } + + Widget dragSelectGrid(BuildContext context, List assets, + double anchor, SliverGap bottomGap) { + return SliverToBoxAdapter( + child: Column( + children: [ + DragSelectGridView( + autoScrollHotspotHeight: 100, + itemBuilder: (BuildContext context, int index, bool selected) { if (gridRevert) { if (index < placeholderCount) { return const SizedBox.shrink(); } index -= placeholderCount; } - return MergeSemantics( + Widget c = MergeSemantics( child: Directionality( textDirection: textDirection, child: assetGridItemBuilder( @@ -1312,92 +1355,47 @@ class DefaultAssetPickerBuilderDelegate ), ), ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); }, - childCount: assetsGridItemCount( + itemCount: assetsGridItemCount( context: context, assets: assets, placeholderCount: placeholderCount, specialItem: specialItem, ), - findChildIndexCallback: (Key? key) { - if (key is ValueKey) { - return findChildIndexBuilder( - id: key.value, - assets: assets, - placeholderCount: placeholderCount, - ); - } - return null; - }, + shrinkWrap: true, // Explicitly disable semantic indexes for custom usage. addSemanticIndexes: false, - ), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - mainAxisSpacing: itemSpacing, - crossAxisSpacing: itemSpacing, - ), - ), - // Ignore the gap when the [anchor] is not equal to 1. - if (gridRevert && anchor == 1) bottomGap, - if (gridRevert) - SliverToBoxAdapter( - key: gridRevertKey, - child: const SizedBox.shrink(), - ), - if (isAppleOS(context) && !gridRevert) bottomGap, - ], + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, + ), + ) + ] + ) ); } - Widget dragSelectGrid(BuildContext context, List assets, + Widget createGrid(BuildContext context, List assets, double anchor, SliverGap bottomGap) { - return DragSelectGridView( - autoScrollHotspotHeight: 100, - itemBuilder: (BuildContext context, int index, bool selected) { - if (gridRevert) { - if (index < placeholderCount) { - return const SizedBox.shrink(); - } - index -= placeholderCount; - } - Widget c = MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, - ), - ), - ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); - }, - itemCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - shrinkWrap: true, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - crossAxisSpacing: 2, - mainAxisSpacing: 2, - ), - ); + if(isDragEnabled == true) + { + return dragSelectGrid(context, assets, anchor, bottomGap); + } + else + { + return sliverGrid(context, assets, anchor, bottomGap); } + } return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1437,14 +1435,27 @@ class DefaultAssetPickerBuilderDelegate context.bottomPadding + bottomSectionHeight, ); appBarPreferredSize ??= appBar(context).preferredSize; - if(isDragEnabled == true) - { - return dragSelectGrid(context, assets, anchor, bottomGap); - } - else - { - return sliverGrid(context, assets, anchor, bottomGap); - } + return CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + controller: gridScrollController, + anchor: gridRevert ? anchor : 0, + center: gridRevert ? gridRevertKey : null, + slivers: [ + if (isAppleOS(context)) + SliverGap.v( + context.topPadding + appBarPreferredSize!.height, + ), + createGrid(context, assets, anchor, bottomGap), + // Ignore the gap when the [anchor] is not equal to 1. + if (gridRevert && anchor == 1) bottomGap, + if (gridRevert) + SliverToBoxAdapter( + key: gridRevertKey, + child: const SizedBox.shrink(), + ), + if (isAppleOS(context) && !gridRevert) bottomGap, + ] + ); }, ), ), @@ -2141,7 +2152,9 @@ class DefaultAssetPickerBuilderDelegate Feedback.forTap(context); context.read().switchPath(wrapper); isSwitchingPath.value = false; - gridScrollController.jumpTo(0); + if (gridScrollController.hasClients) { + gridScrollController.jumpTo(0); + } }, child: SizedBox( height: isAppleOS(context) ? 64 : 52, From 1d47f51c779fbb96b7890c3ac43588306b466bf2 Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Thu, 7 Nov 2024 02:31:15 -0600 Subject: [PATCH 14/15] Fixed issue where drag mode was bringing in all photos on load --- .../asset_picker_builder_delegate.dart | 209 +++++++++--------- 1 file changed, 104 insertions(+), 105 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 09242060..99860e55 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1282,69 +1282,25 @@ class DefaultAssetPickerBuilderDelegate Widget sliverGrid(BuildContext context, List assets, double anchor, SliverGap bottomGap) { - return SliverGrid( - delegate: SliverChildBuilderDelegate( - (context, int index) { - if (gridRevert) { - if (index < placeholderCount) { - return const SizedBox.shrink(); - } - index -= placeholderCount; - } - return MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, - ), - ), - ); - }, - childCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - findChildIndexCallback: (Key? key) { - if (key is ValueKey) { - return findChildIndexBuilder( - id: key.value, - assets: assets, - placeholderCount: placeholderCount, - ); - } - return null; - }, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - ), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - mainAxisSpacing: itemSpacing, - crossAxisSpacing: itemSpacing, - ), - ); - } - - Widget dragSelectGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { - return SliverToBoxAdapter( - child: Column( - children: [ - DragSelectGridView( - autoScrollHotspotHeight: 100, - itemBuilder: (BuildContext context, int index, bool selected) { + return CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + anchor: gridRevert ? anchor : 0, + center: gridRevert ? gridRevertKey : null, + slivers: [ + if (isAppleOS(context)) + SliverGap.v( + context.topPadding + appBarPreferredSize!.height, + ), + SliverGrid( + delegate: SliverChildBuilderDelegate( + (context, int index) { if (gridRevert) { if (index < placeholderCount) { return const SizedBox.shrink(); } index -= placeholderCount; } - Widget c = MergeSemantics( + return MergeSemantics( child: Directionality( textDirection: textDirection, child: assetGridItemBuilder( @@ -1355,47 +1311,110 @@ class DefaultAssetPickerBuilderDelegate ), ), ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); }, - itemCount: assetsGridItemCount( + childCount: assetsGridItemCount( context: context, assets: assets, placeholderCount: placeholderCount, specialItem: specialItem, ), - shrinkWrap: true, + findChildIndexCallback: (Key? key) { + if (key is ValueKey) { + return findChildIndexBuilder( + id: key.value, + assets: assets, + placeholderCount: placeholderCount, + ); + } + return null; + }, // Explicitly disable semantic indexes for custom usage. addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - crossAxisSpacing: 2, - mainAxisSpacing: 2, - ), + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + mainAxisSpacing: itemSpacing, + crossAxisSpacing: itemSpacing, ) - ] - ) + ), + // Ignore the gap when the [anchor] is not equal to 1. + if (gridRevert && anchor == 1) bottomGap, + if (gridRevert) + SliverToBoxAdapter( + key: gridRevertKey, + child: const SizedBox.shrink(), + ), + if (isAppleOS(context) && !gridRevert) bottomGap, + ] ); } - Widget createGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { - if(isDragEnabled == true) - { - return dragSelectGrid(context, assets, anchor, bottomGap); + Widget dragSelectGrid(BuildContext context, List assets, + double anchor, SliverGap bottomGap) { + bool reverse = false; + if(effectiveGridDirection(context) == TextDirection.rtl) + { + reverse = true; + } + return DragSelectGridView( + reverse: reverse, + autoScrollHotspotHeight: 100, + itemBuilder: (BuildContext context, int index, bool selected) { + if (gridRevert) { + if (index < placeholderCount) { + return const SizedBox.shrink(); + } + index -= placeholderCount; + } + Widget c = MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, + ) + ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, + ), + ); } - else - { - return sliverGrid(context, assets, anchor, bottomGap); + + Widget createGrid(BuildContext context, List assets, + double anchor, SliverGap bottomGap) { + if(isDragEnabled == true) + { + return dragSelectGrid(context, assets, anchor, bottomGap); + } + else + { + return sliverGrid(context, assets, anchor, bottomGap); + } } - } return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { @@ -1435,27 +1454,7 @@ class DefaultAssetPickerBuilderDelegate context.bottomPadding + bottomSectionHeight, ); appBarPreferredSize ??= appBar(context).preferredSize; - return CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: gridScrollController, - anchor: gridRevert ? anchor : 0, - center: gridRevert ? gridRevertKey : null, - slivers: [ - if (isAppleOS(context)) - SliverGap.v( - context.topPadding + appBarPreferredSize!.height, - ), - createGrid(context, assets, anchor, bottomGap), - // Ignore the gap when the [anchor] is not equal to 1. - if (gridRevert && anchor == 1) bottomGap, - if (gridRevert) - SliverToBoxAdapter( - key: gridRevertKey, - child: const SizedBox.shrink(), - ), - if (isAppleOS(context) && !gridRevert) bottomGap, - ] - ); + return createGrid(context, assets, anchor, bottomGap); }, ), ), From 54543d6c3e572fd8634f170cedd5f4250fa6380f Mon Sep 17 00:00:00 2001 From: Lucas Winkelman Date: Thu, 7 Nov 2024 14:13:47 -0600 Subject: [PATCH 15/15] It seems that padding is working --- .../asset_picker_builder_delegate.dart | 140 ++++++++++-------- 1 file changed, 80 insertions(+), 60 deletions(-) diff --git a/lib/src/delegates/asset_picker_builder_delegate.dart b/lib/src/delegates/asset_picker_builder_delegate.dart index 99860e55..55a1a802 100644 --- a/lib/src/delegates/asset_picker_builder_delegate.dart +++ b/lib/src/delegates/asset_picker_builder_delegate.dart @@ -1281,16 +1281,18 @@ class DefaultAssetPickerBuilderDelegate final textDirection = Directionality.of(context); Widget sliverGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { + double anchor, double topHeight, double bottomHeight) { + final SliverGap bottomGap = SliverGap.v( + bottomHeight, + ); return CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), anchor: gridRevert ? anchor : 0, center: gridRevert ? gridRevertKey : null, slivers: [ - if (isAppleOS(context)) - SliverGap.v( - context.topPadding + appBarPreferredSize!.height, - ), + SliverGap.v( + topHeight, + ), SliverGrid( delegate: SliverChildBuilderDelegate( (context, int index) { @@ -1337,82 +1339,86 @@ class DefaultAssetPickerBuilderDelegate crossAxisSpacing: itemSpacing, ) ), - // Ignore the gap when the [anchor] is not equal to 1. - if (gridRevert && anchor == 1) bottomGap, if (gridRevert) SliverToBoxAdapter( key: gridRevertKey, child: const SizedBox.shrink(), ), - if (isAppleOS(context) && !gridRevert) bottomGap, + bottomGap, ] ); } Widget dragSelectGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { + double anchor, double topHeight, double bottomHeight) { bool reverse = false; if(effectiveGridDirection(context) == TextDirection.rtl) { reverse = true; } - return DragSelectGridView( - reverse: reverse, - autoScrollHotspotHeight: 100, - itemBuilder: (BuildContext context, int index, bool selected) { - if (gridRevert) { - if (index < placeholderCount) { - return const SizedBox.shrink(); - } - index -= placeholderCount; - } - Widget c = MergeSemantics( - child: Directionality( - textDirection: textDirection, - child: assetGridItemBuilder( - context, - index, - assets, - specialItem: specialItem, - ) - ), - ); - return SelectableItem( - index: index, - color: Colors.blue, - selected: selected, - child: c, - asset: assets[index], - parent: this, - context: context - ); - }, - itemCount: assetsGridItemCount( - context: context, - assets: assets, - placeholderCount: placeholderCount, - specialItem: specialItem, - ), - shrinkWrap: true, - // Explicitly disable semantic indexes for custom usage. - addSemanticIndexes: false, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: gridCount, - crossAxisSpacing: 2, - mainAxisSpacing: 2, + return Padding( + padding: EdgeInsets.only( + top: topHeight, + bottom: bottomHeight ), + child: DragSelectGridView( + reverse: reverse, + autoScrollHotspotHeight: 100, + itemBuilder: (BuildContext context, int index, bool selected) { + if (gridRevert) { + if (index < placeholderCount) { + return const SizedBox.shrink(); + } + index -= placeholderCount; + } + Widget c = MergeSemantics( + child: Directionality( + textDirection: textDirection, + child: assetGridItemBuilder( + context, + index, + assets, + specialItem: specialItem, + ) + ), + ); + return SelectableItem( + index: index, + color: Colors.blue, + selected: selected, + child: c, + asset: assets[index], + parent: this, + context: context + ); + }, + itemCount: assetsGridItemCount( + context: context, + assets: assets, + placeholderCount: placeholderCount, + specialItem: specialItem, + ), + shrinkWrap: true, + // Explicitly disable semantic indexes for custom usage. + addSemanticIndexes: false, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: gridCount, + crossAxisSpacing: 2, + mainAxisSpacing: 2, + ), + ) ); } Widget createGrid(BuildContext context, List assets, - double anchor, SliverGap bottomGap) { + double anchor, double topHeight, double bottomHeight) { if(isDragEnabled == true) { - return dragSelectGrid(context, assets, anchor, bottomGap); + return dragSelectGrid(context, assets, anchor, topHeight, bottomHeight); } else { - return sliverGrid(context, assets, anchor, bottomGap); + return sliverGrid(context, assets, anchor, topHeight, bottomHeight); } } @@ -1442,6 +1448,23 @@ class DefaultAssetPickerBuilderDelegate 1, ); + double bottomHeight = 0; + // Ignore the gap when the [anchor] is not equal to 1. + if (gridRevert && anchor == 1) + { + bottomHeight = context.bottomPadding + bottomSectionHeight; + } + if (isAppleOS(context) && !gridRevert) + { + bottomHeight = context.bottomPadding + bottomSectionHeight; + } + + double topHeight = 0; + if(isAppleOS(context)) + { + topHeight = context.topPadding + appBarPreferredSize!.height; + } + return Directionality( textDirection: effectiveGridDirection(context), child: ColoredBox( @@ -1450,11 +1473,8 @@ class DefaultAssetPickerBuilderDelegate selector: (_, DefaultAssetPickerProvider p) => p.currentAssets, builder: (BuildContext context, List assets, _) { - final SliverGap bottomGap = SliverGap.v( - context.bottomPadding + bottomSectionHeight, - ); appBarPreferredSize ??= appBar(context).preferredSize; - return createGrid(context, assets, anchor, bottomGap); + return createGrid(context, assets, anchor, topHeight, bottomHeight); }, ), ),