Skip to content

Commit b2a3669

Browse files
committed
✨ Refactored grid layout for iOS reverted grid
1 parent 45afcb5 commit b2a3669

File tree

1 file changed

+60
-55
lines changed

1 file changed

+60
-55
lines changed

lib/src/delegates/asset_picker_builder_delegate.dart

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -758,26 +758,39 @@ class DefaultAssetPickerBuilderDelegate
758758
@override
759759
Widget assetsGridBuilder(BuildContext context) {
760760
// First, we need the count of the assets.
761-
final int totalCount = provider.currentPathEntity!.assetCount;
762-
// Then we use the total count to calculate how many placeholders we need.
763-
final int _placeholderCount;
764-
if (isAppleOS) {
765-
_placeholderCount =
766-
totalCount % gridCount == 0 ? 0 : gridCount - totalCount % gridCount;
761+
int totalCount = provider.currentPathEntity!.assetCount;
762+
// If user chose a special item's position, add 1 count.
763+
if (specialItemPosition != SpecialItemPosition.none) {
764+
totalCount += 1;
765+
}
766+
// Then we use the [totalCount] to calculate how many placeholders we need.
767+
final int placeholderCount;
768+
if (isAppleOS && totalCount % gridCount != 0) {
769+
// When there are left items that not filled into one row, filled the row
770+
// with placeholders.
771+
placeholderCount = gridCount - totalCount % gridCount;
767772
} else {
768-
_placeholderCount = 0;
773+
// Otherwise, we don't need placeholders.
774+
placeholderCount = 0;
769775
}
770-
771-
Widget _sliverGrid(BuildContext c, List<AssetEntity> assets) {
776+
// Calculate rows count.
777+
final int row = (totalCount + placeholderCount) ~/ gridCount;
778+
// Here we got a magic calculation. [itemSpacing] needs to be divided by
779+
// [gridCount] since every grid item is squeezed by the [itemSpacing],
780+
// and it's actual size is reduced with [itemSpacing / gridCount].
781+
final double dividedSpacing = itemSpacing / gridCount;
782+
final double topPadding = context.mediaQuery.padding.top + kToolbarHeight;
783+
784+
Widget _sliverGrid(BuildContext ctx, List<AssetEntity> assets) {
772785
return SliverGrid(
773786
delegate: SliverChildBuilderDelegate(
774787
(_, int index) => Builder(
775788
builder: (BuildContext c) {
776789
if (isAppleOS) {
777-
if (index < _placeholderCount) {
790+
if (index < placeholderCount) {
778791
return const SizedBox.shrink();
779792
}
780-
index -= _placeholderCount;
793+
index -= placeholderCount;
781794
}
782795
return Directionality(
783796
textDirection: Directionality.of(context),
@@ -786,16 +799,16 @@ class DefaultAssetPickerBuilderDelegate
786799
},
787800
),
788801
childCount: assetsGridItemCount(
789-
context: c,
802+
context: ctx,
790803
assets: assets,
791-
placeholderCount: _placeholderCount,
804+
placeholderCount: placeholderCount,
792805
),
793806
findChildIndexCallback: (Key? key) {
794807
if (key is ValueKey<String>) {
795808
return findChildIndexBuilder(
796809
id: key.value,
797810
assets: assets,
798-
placeholderCount: _placeholderCount,
811+
placeholderCount: placeholderCount,
799812
);
800813
}
801814
return null;
@@ -811,24 +824,16 @@ class DefaultAssetPickerBuilderDelegate
811824

812825
return LayoutBuilder(
813826
builder: (BuildContext c, BoxConstraints constraints) {
814-
final double topPadding = c.mediaQuery.padding.top + kToolbarHeight;
815-
final double bottomPadding =
816-
c.mediaQuery.padding.bottom + bottomActionBarHeight;
817-
final double verticalPadding = topPadding + bottomPadding;
818-
819-
final int _count = totalCount + _placeholderCount;
820-
final double _wWidth = constraints.maxWidth;
821-
final double _wHeight = constraints.maxHeight - topPadding;
822-
final double _itemSize = _wWidth / gridCount;
823-
final double anchor;
824-
if (_count <= gridCount) {
825-
anchor = verticalPadding / _wHeight;
826-
} else {
827-
anchor = math.min(
828-
_count ~/ gridCount * _itemSize / _wHeight,
829-
1,
830-
);
831-
}
827+
final double _itemSize = constraints.maxWidth / gridCount;
828+
// Use [ScrollView.anchor] to determine where is the first place of
829+
// the [SliverGrid]. Each row needs [dividedSpacing] to calculate,
830+
// then minus one times of [itemSpacing] because spacing's count in the
831+
// cross axis is always less than the rows.
832+
final double anchor = math.min(
833+
(row * (_itemSize + dividedSpacing) + topPadding - itemSpacing) /
834+
constraints.maxHeight,
835+
1,
836+
);
832837

833838
return Directionality(
834839
textDirection: effectiveGridDirection(context),
@@ -837,29 +842,29 @@ class DefaultAssetPickerBuilderDelegate
837842
child: Selector<DefaultAssetPickerProvider, List<AssetEntity>>(
838843
selector: (_, DefaultAssetPickerProvider provider) =>
839844
provider.currentAssets,
840-
builder: (BuildContext c, List<AssetEntity> assets, __) {
841-
return CustomScrollView(
842-
physics: const AlwaysScrollableScrollPhysics(),
843-
controller: gridScrollController,
844-
anchor: isAppleOS ? anchor : 0,
845-
center: isAppleOS ? _gridRevertKey : null,
846-
slivers: <Widget>[
847-
if (isAppleOS)
848-
SliverToBoxAdapter(
849-
child: SizedBox(
850-
height:
851-
context.mediaQuery.padding.top + kToolbarHeight,
852-
),
853-
),
854-
_sliverGrid(c, assets),
855-
if (isAppleOS)
856-
SliverToBoxAdapter(
857-
key: _gridRevertKey,
858-
child: const SizedBox.shrink(),
859-
),
860-
],
861-
);
862-
},
845+
builder: (_, List<AssetEntity> assets, __) => CustomScrollView(
846+
physics: const AlwaysScrollableScrollPhysics(),
847+
controller: gridScrollController,
848+
anchor: isAppleOS ? anchor : 0,
849+
center: isAppleOS ? _gridRevertKey : null,
850+
slivers: <Widget>[
851+
if (isAppleOS)
852+
SliverGap.v(
853+
context.mediaQuery.padding.top + kToolbarHeight,
854+
),
855+
_sliverGrid(_, assets),
856+
// Ignore the gap when the [anchor] is not equal to 1.
857+
if (isAppleOS && anchor == 1)
858+
SliverGap.v(
859+
context.mediaQuery.padding.bottom + bottomActionBarHeight,
860+
),
861+
if (isAppleOS)
862+
SliverToBoxAdapter(
863+
key: _gridRevertKey,
864+
child: const SizedBox.shrink(),
865+
),
866+
],
867+
),
863868
),
864869
),
865870
);

0 commit comments

Comments
 (0)