Skip to content

Commit 0611955

Browse files
committed
🎨 Improve assetsGridBuilder in custom delegate
1 parent 1b7d39a commit 0611955

File tree

1 file changed

+107
-50
lines changed

1 file changed

+107
-50
lines changed

example/lib/customs/pickers/directory_file_asset_picker.dart

Lines changed: 107 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -534,58 +534,115 @@ class FileAssetPickerBuilder
534534

535535
@override
536536
Widget assetsGridBuilder(BuildContext context) {
537-
return ColoredBox(
538-
color: theme.canvasColor,
539-
child: Selector<FileAssetPickerProvider, List<File>>(
540-
selector: (_, FileAssetPickerProvider provider) =>
541-
provider.currentAssets,
542-
builder: (_, List<File> currentAssets, __) => CustomScrollView(
543-
controller: gridScrollController,
544-
slivers: <Widget>[
545-
if (isAppleOS)
546-
SliverToBoxAdapter(
547-
child: SizedBox(
548-
height: Screens.topSafeHeight + kToolbarHeight,
549-
),
550-
),
551-
SliverGrid(
552-
delegate: SliverChildBuilderDelegate(
553-
(_, int index) => Builder(
554-
builder: (BuildContext c) => assetGridItemBuilder(
555-
c,
556-
index,
557-
currentAssets,
558-
),
559-
),
560-
childCount: assetsGridItemCount(
561-
context: _,
562-
assets: currentAssets,
563-
),
564-
findChildIndexCallback: (Key? key) {
565-
if (key is ValueKey<String>) {
566-
return findChildIndexBuilder(
567-
id: key.value,
568-
assets: currentAssets,
569-
);
570-
}
571-
return null;
572-
},
573-
),
574-
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
575-
crossAxisCount: gridCount,
576-
mainAxisSpacing: itemSpacing,
577-
crossAxisSpacing: itemSpacing,
537+
int totalCount = provider.currentAssets.length;
538+
if (specialItemPosition != SpecialItemPosition.none) {
539+
totalCount += 1;
540+
}
541+
final int placeholderCount;
542+
if (isAppleOS && totalCount % gridCount != 0) {
543+
placeholderCount = gridCount - totalCount % gridCount;
544+
} else {
545+
placeholderCount = 0;
546+
}
547+
final int row = (totalCount + placeholderCount) ~/ gridCount;
548+
final double dividedSpacing = itemSpacing / gridCount;
549+
final double topPadding =
550+
MediaQuery.of(context).padding.top + kToolbarHeight;
551+
552+
Widget _sliverGrid(BuildContext ctx, List<File> assets) {
553+
return SliverGrid(
554+
delegate: SliverChildBuilderDelegate(
555+
(_, int index) => Builder(
556+
builder: (BuildContext c) {
557+
if (isAppleOS) {
558+
if (index < placeholderCount) {
559+
return const SizedBox.shrink();
560+
}
561+
index -= placeholderCount;
562+
}
563+
return Directionality(
564+
textDirection: Directionality.of(context),
565+
child: assetGridItemBuilder(c, index, assets),
566+
);
567+
},
568+
),
569+
childCount: assetsGridItemCount(
570+
context: ctx,
571+
assets: assets,
572+
placeholderCount: placeholderCount,
573+
),
574+
findChildIndexCallback: (Key? key) {
575+
if (key is ValueKey<String>) {
576+
return findChildIndexBuilder(
577+
id: key.value,
578+
assets: assets,
579+
placeholderCount: placeholderCount,
580+
);
581+
}
582+
return null;
583+
},
584+
),
585+
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
586+
crossAxisCount: gridCount,
587+
mainAxisSpacing: itemSpacing,
588+
crossAxisSpacing: itemSpacing,
589+
),
590+
);
591+
}
592+
593+
return LayoutBuilder(
594+
builder: (BuildContext c, BoxConstraints constraints) {
595+
final double _itemSize = constraints.maxWidth / gridCount;
596+
// Use [ScrollView.anchor] to determine where is the first place of
597+
// the [SliverGrid]. Each row needs [dividedSpacing] to calculate,
598+
// then minus one times of [itemSpacing] because spacing's count in the
599+
// cross axis is always less than the rows.
600+
final double anchor = math.min(
601+
(row * (_itemSize + dividedSpacing) + topPadding - itemSpacing) /
602+
constraints.maxHeight,
603+
1,
604+
);
605+
606+
return Directionality(
607+
textDirection: effectiveGridDirection(context),
608+
child: ColoredBox(
609+
color: theme.canvasColor,
610+
child: Selector<FileAssetPickerProvider, List<File>>(
611+
selector: (_, FileAssetPickerProvider provider) =>
612+
provider.currentAssets,
613+
builder: (_, List<File> assets, __) => CustomScrollView(
614+
physics: const AlwaysScrollableScrollPhysics(),
615+
controller: gridScrollController,
616+
anchor: isAppleOS ? anchor : 0,
617+
center: isAppleOS ? gridRevertKey : null,
618+
slivers: <Widget>[
619+
if (isAppleOS)
620+
SliverToBoxAdapter(
621+
child: SizedBox(
622+
height:
623+
MediaQuery.of(context).padding.top + kToolbarHeight,
624+
),
625+
),
626+
_sliverGrid(_, assets),
627+
// Ignore the gap when the [anchor] is not equal to 1.
628+
if (isAppleOS && anchor == 1)
629+
SliverToBoxAdapter(
630+
child: SizedBox(
631+
height: MediaQuery.of(context).padding.bottom +
632+
bottomActionBarHeight,
633+
),
634+
),
635+
if (isAppleOS)
636+
SliverToBoxAdapter(
637+
key: gridRevertKey,
638+
child: const SizedBox.shrink(),
639+
),
640+
],
578641
),
579642
),
580-
if (isAppleOS)
581-
SliverToBoxAdapter(
582-
child: SizedBox(
583-
height: Screens.bottomSafeHeight + bottomActionBarHeight,
584-
),
585-
),
586-
],
587-
),
588-
),
643+
),
644+
);
645+
},
589646
);
590647
}
591648

0 commit comments

Comments
 (0)