Skip to content

Commit 724fa95

Browse files
committed
💄 Sync UI details for the viewer
1 parent debd10f commit 724fa95

File tree

1 file changed

+43
-17
lines changed

1 file changed

+43
-17
lines changed

lib/src/delegates/asset_picker_viewer_builder_delegate.dart

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
///
55
import 'dart:async';
66
import 'dart:io';
7+
import 'dart:math' as math;
78

89
import 'package:flutter/material.dart';
910
import 'package:flutter/services.dart';
@@ -47,13 +48,17 @@ abstract class AssetPickerViewerBuilderDelegate<A, P> {
4748
/// [StreamController] for viewing page index update.
4849
/// 用于更新当前正在浏览的资源页码的流控制器
4950
///
50-
/// The main purpose is narrow down build parts when page index is changing,
51+
/// The main purpose is to narrow down build parts when index is changing,
5152
/// prevent widely [setState] and causing other widgets rebuild.
5253
/// 使用 [StreamController] 的主要目的是缩小页码变化时构建组件的范围,
5354
/// 防止滥用 [setState] 导致其他部件重新构建。
5455
final StreamController<int> pageStreamController =
5556
StreamController<int>.broadcast();
5657

58+
/// The [ScrollController] for the previewing assets list.
59+
/// 正在预览的资源的 [ScrollController]
60+
final ScrollController previewingListController = ScrollController();
61+
5762
/// The [State] for a viewer.
5863
/// 预览器的状态实例
5964
late final AssetPickerViewerState<A, P> viewerState;
@@ -103,12 +108,18 @@ abstract class AssetPickerViewerBuilderDelegate<A, P> {
103108
/// 保留一个 dispose 方法与 [State] 同步。
104109
void dispose() {
105110
pageStreamController.close();
111+
previewingListController.dispose();
112+
selectedNotifier.dispose();
106113
}
107114

108115
/// The length getter for selected assets currently.
109116
/// 当前选中的资源的长度获取
110117
int get selectedCount => selectedAssets?.length ?? 0;
111118

119+
/// 是否已经选择了最大数量的资源
120+
bool get selectedMaximumAssets =>
121+
selectedAssets != null && selectedAssets!.length == maxAssets;
122+
112123
/// Construct a notifier to notify
113124
/// whether if a new asset is selected or unselected.
114125
/// 构造一个通知器,在新资源选中或取消选中时通知。
@@ -289,6 +300,7 @@ class DefaultAssetPickerViewerBuilderDelegate
289300
@override
290301
void dispose() {
291302
_doubleTapAnimationController.dispose();
303+
pageController.dispose();
292304
super.dispose();
293305
}
294306

@@ -456,18 +468,20 @@ class DefaultAssetPickerViewerBuilderDelegate
456468
valueListenable: selectedNotifier,
457469
builder: (_, int count, __) => Container(
458470
width: count > 0 ? double.maxFinite : 0,
459-
height: 90,
471+
height: bottomPreviewHeight,
460472
color: _backgroundColor,
461473
child: ListView.builder(
474+
controller: previewingListController,
462475
scrollDirection: Axis.horizontal,
463476
padding: const EdgeInsets.symmetric(horizontal: 5.0),
477+
physics: const ClampingScrollPhysics(),
464478
itemCount: count,
465479
itemBuilder: bottomDetailItemBuilder,
466480
),
467481
),
468482
),
469483
Container(
470-
height: 50,
484+
height: bottomBarHeight,
471485
padding: const EdgeInsets.symmetric(horizontal: 20.0),
472486
decoration: BoxDecoration(
473487
border: Border(
@@ -498,8 +512,12 @@ class DefaultAssetPickerViewerBuilderDelegate
498512

499513
@override
500514
Widget bottomDetailItemBuilder(BuildContext context, int index) {
515+
const double padding = 8.0;
501516
return Padding(
502-
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
517+
padding: const EdgeInsets.symmetric(
518+
horizontal: padding,
519+
vertical: padding * 2,
520+
),
503521
child: AspectRatio(
504522
aspectRatio: 1.0,
505523
child: StreamBuilder<int>(
@@ -522,9 +540,24 @@ class DefaultAssetPickerViewerBuilderDelegate
522540
}();
523541
return GestureDetector(
524542
onTap: () {
543+
if (pageController.page == index.toDouble()) {
544+
return;
545+
}
546+
final int page;
525547
if (previewAssets != selectedAssets) {
526-
pageController.jumpToPage(previewAssets.indexOf(asset));
548+
page = previewAssets.indexOf(asset);
549+
} else {
550+
page = index;
527551
}
552+
pageController.jumpToPage(page);
553+
final double offset =
554+
(index - 0.5) * (bottomPreviewHeight - padding * 3) -
555+
context.mediaQuery.size.width / 4;
556+
previewingListController.animateTo(
557+
math.max(0, offset),
558+
curve: Curves.ease,
559+
duration: kThemeChangeDuration,
560+
);
528561
},
529562
child: Selector<AssetPickerViewerProvider<AssetEntity>?,
530563
List<AssetEntity>?>(
@@ -548,7 +581,7 @@ class DefaultAssetPickerViewerBuilderDelegate
548581
border: isViewing
549582
? Border.all(
550583
color: themeData.colorScheme.secondary,
551-
width: 2.0,
584+
width: 3,
552585
)
553586
: null,
554587
color: isSelected
@@ -691,6 +724,9 @@ class DefaultAssetPickerViewerBuilderDelegate
691724
/// Select button for apple OS.
692725
/// 苹果系列系统的选择按钮
693726
Widget _appleOSSelectButton(bool isSelected, AssetEntity asset) {
727+
if (!isSelected && selectedMaximumAssets) {
728+
return const SizedBox.shrink();
729+
}
694730
return Padding(
695731
padding: const EdgeInsetsDirectional.only(end: 10.0),
696732
child: GestureDetector(
@@ -712,17 +748,7 @@ class DefaultAssetPickerViewerBuilderDelegate
712748
color: isSelected ? themeData.buttonColor : null,
713749
shape: BoxShape.circle,
714750
),
715-
child: Center(
716-
child: isSelected
717-
? Text(
718-
'${selectedAssets!.indexOf(asset) + 1}',
719-
style: const TextStyle(
720-
fontSize: 16.0,
721-
fontWeight: FontWeight.bold,
722-
),
723-
)
724-
: const Icon(Icons.check, size: 20.0),
725-
),
751+
child: const Center(child: Icon(Icons.check, size: 20.0)),
726752
),
727753
),
728754
);

0 commit comments

Comments
 (0)