Skip to content

Commit 2300382

Browse files
authored
✨ Ability to disable preview of assets using SpecialPickerType.noPreview (#102)
1 parent 8812f71 commit 2300382

File tree

5 files changed

+135
-67
lines changed

5 files changed

+135
-67
lines changed

example/lib/pages/multi_assets_page.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,23 @@ class _MultiAssetsPageState extends State<MultiAssetsPage> {
191191
);
192192
},
193193
),
194+
PickMethodModel(
195+
icon: '🚀',
196+
name: 'No preview',
197+
description: 'Pick assets like the WhatsApp/MegaTok pattern.',
198+
method: (
199+
BuildContext context,
200+
List<AssetEntity> assets,
201+
) async {
202+
return await AssetPicker.pickAssets(
203+
context,
204+
maxAssets: maxAssetsCount,
205+
selectedAssets: assets,
206+
requestType: RequestType.common,
207+
specialPickerType: SpecialPickerType.noPreview,
208+
);
209+
},
210+
),
194211
PickMethodModel(
195212
icon: '🎚',
196213
name: 'Custom image preview thumb size',

example/lib/pages/single_assets_page.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,23 @@ class _SingleAssetPageState extends State<SingleAssetPage> {
186186
);
187187
},
188188
),
189+
PickMethodModel(
190+
icon: '🚀',
191+
name: 'No preview',
192+
description: 'Pick assets like the WhatsApp/MegaTok pattern.',
193+
method: (
194+
BuildContext context,
195+
List<AssetEntity> assets,
196+
) async {
197+
return await AssetPicker.pickAssets(
198+
context,
199+
maxAssets: maxAssetsCount,
200+
selectedAssets: assets,
201+
requestType: RequestType.common,
202+
specialPickerType: SpecialPickerType.noPreview,
203+
);
204+
},
205+
),
189206
];
190207

191208
Future<void> selectAssets(PickMethodModel model) async {

lib/src/constants/enums.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,27 @@
66
/// Provide some special picker types to integrate
77
/// un-common pick pattern.
88
/// 提供一些特殊的选择器类型以整合非常规的选择行为。
9-
enum SpecialPickerType { wechatMoment }
9+
enum SpecialPickerType {
10+
/// WeChat Moments mode.
11+
/// 微信朋友圈模式
12+
///
13+
/// The user can only select *one video* or *multiple images* at the same time,
14+
/// and those two asset types cannot be selected at the same time.
15+
/// 用户只可以选择 **一个视频** 或 **多个图片**,并且两种类型互斥。
16+
wechatMoment,
17+
18+
/// Disable preview of assets.
19+
/// 禁用资源预览
20+
///
21+
/// There is no preview mode when clicking grid items.
22+
/// In multiple select mode, any click (either on the select indicator or on
23+
/// the asset itself) will select the asset.
24+
/// In single select mode, any click directly selects the asset and returns.
25+
/// 用户在点击网格的 item 时无法进入预览。
26+
/// 在多选模式下无论点击选择指示还是 item 都将触发选择,
27+
/// 而在单选模式下将直接返回点击的资源。
28+
noPreview,
29+
}
1030

1131
/// Provide an item slot for custom widget insertion.
1232
/// 提供一个自定义位置供特殊item放入资源列表中。

lib/src/delegates/asset_picker_builder_delegate.dart

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -455,12 +455,15 @@ class DefaultAssetPickerBuilderDelegate
455455
/// The current special picker type for the picker.
456456
/// 当前特殊选择类型
457457
///
458-
/// There're several types which are special:
458+
/// Several types which are special:
459459
/// * [SpecialPickerType.wechatMoment] When user selected video, no more images
460460
/// can be selected.
461+
/// * [SpecialPickerType.noPreview] Disable preview of asset; Clicking on an
462+
/// asset selects it.
461463
///
462464
/// 这里包含一些特殊选择类型:
463465
/// * [SpecialPickerType.wechatMoment] 微信朋友圈模式。当用户选择了视频,将不能选择图片。
466+
/// * [SpecialPickerType.noPreview] 禁用资源预览。多选时单击资产将直接选中,单选时选中并返回。
464467
final SpecialPickerType? specialPickerType;
465468

466469
/// [Duration] when triggering path switching.
@@ -471,6 +474,10 @@ class DefaultAssetPickerBuilderDelegate
471474
/// 切换路径时的动画曲线
472475
Curve get switchingPathCurve => Curves.easeInOut;
473476

477+
/// Whether the preview of assets is enabled.
478+
/// 资源的预览是否启用
479+
bool get isPreviewEnabled => specialPickerType != SpecialPickerType.noPreview;
480+
474481
@override
475482
Widget androidLayout(BuildContext context) {
476483
return FixedAppBarWrapper(
@@ -491,7 +498,8 @@ class DefaultAssetPickerBuilderDelegate
491498
child: Column(
492499
children: <Widget>[
493500
Expanded(child: assetsGridBuilder(context)),
494-
if (!isSingleAssetMode) bottomActionBar(context),
501+
if (!isSingleAssetMode && isPreviewEnabled)
502+
bottomActionBar(context),
495503
],
496504
),
497505
),
@@ -513,7 +521,9 @@ class DefaultAssetPickerBuilderDelegate
513521
centerTitle: isAppleOS,
514522
title: pathEntitySelector(context),
515523
leading: backButton(context),
516-
actions: !isAppleOS ? <Widget>[confirmButton(context)] : null,
524+
actions: !isAppleOS && (isPreviewEnabled || !isSingleAssetMode)
525+
? <Widget>[confirmButton(context)]
526+
: null,
517527
actionsPadding: const EdgeInsets.only(right: 14.0),
518528
blurRadius: isAppleOS ? appleOSBlurRadius : 0.0,
519529
);
@@ -537,7 +547,8 @@ class DefaultAssetPickerBuilderDelegate
537547
Positioned.fill(
538548
child: assetsGridBuilder(context),
539549
),
540-
if (!isSingleAssetMode || isAppleOS)
550+
if ((!isSingleAssetMode || isAppleOS) &&
551+
isPreviewEnabled)
541552
PositionedDirectional(
542553
bottom: 0.0,
543554
child: bottomActionBar(context),
@@ -1148,63 +1159,67 @@ class DefaultAssetPickerBuilderDelegate
11481159
);
11491160
final bool selected = selectedAssets.contains(asset);
11501161
final double indicatorSize = Screens.width / gridCount / 3;
1151-
return Positioned(
1152-
top: 0.0,
1153-
right: 0.0,
1154-
child: GestureDetector(
1155-
behavior: HitTestBehavior.opaque,
1156-
onTap: () {
1157-
if (selected) {
1158-
provider.unSelectAsset(asset);
1159-
} else {
1160-
if (isSingleAssetMode) {
1161-
provider.selectedAssets.clear();
1162-
}
1163-
provider.selectAsset(asset);
1162+
final Widget innerSelector = AnimatedContainer(
1163+
duration: switchingPathDuration,
1164+
width: indicatorSize / (isAppleOS ? 1.25 : 1.5),
1165+
height: indicatorSize / (isAppleOS ? 1.25 : 1.5),
1166+
decoration: BoxDecoration(
1167+
border:
1168+
!selected ? Border.all(color: Colors.white, width: 2.0) : null,
1169+
color: selected ? themeColor : null,
1170+
shape: BoxShape.circle,
1171+
),
1172+
child: AnimatedSwitcher(
1173+
duration: switchingPathDuration,
1174+
reverseDuration: switchingPathDuration,
1175+
child: selected
1176+
? isSingleAssetMode
1177+
? const Icon(Icons.check, size: 18.0)
1178+
: Text(
1179+
'${selectedAssets.indexOf(asset) + 1}',
1180+
style: TextStyle(
1181+
color: selected
1182+
? theme.textTheme.bodyText1?.color
1183+
: null,
1184+
fontSize: isAppleOS ? 16.0 : 14.0,
1185+
fontWeight:
1186+
isAppleOS ? FontWeight.w600 : FontWeight.bold,
1187+
),
1188+
)
1189+
: const SizedBox.shrink(),
1190+
),
1191+
);
1192+
final GestureDetector selectorWidget = GestureDetector(
1193+
behavior: HitTestBehavior.opaque,
1194+
onTap: () {
1195+
if (selected) {
1196+
provider.unSelectAsset(asset);
1197+
} else {
1198+
if (isSingleAssetMode) {
1199+
provider.selectedAssets.clear();
11641200
}
1165-
},
1166-
child: Container(
1167-
margin: EdgeInsets.all(
1168-
Screens.width / gridCount / (isAppleOS ? 12.0 : 15.0),
1169-
),
1170-
width: indicatorSize,
1171-
height: indicatorSize,
1172-
alignment: AlignmentDirectional.topEnd,
1173-
child: AnimatedContainer(
1174-
duration: switchingPathDuration,
1175-
width: indicatorSize / (isAppleOS ? 1.25 : 1.5),
1176-
height: indicatorSize / (isAppleOS ? 1.25 : 1.5),
1177-
decoration: BoxDecoration(
1178-
border: !selected
1179-
? Border.all(color: Colors.white, width: 2.0)
1180-
: null,
1181-
color: selected ? themeColor : null,
1182-
shape: BoxShape.circle,
1183-
),
1184-
child: AnimatedSwitcher(
1185-
duration: switchingPathDuration,
1186-
reverseDuration: switchingPathDuration,
1187-
child: selected
1188-
? isSingleAssetMode
1189-
? const Icon(Icons.check, size: 18.0)
1190-
: Text(
1191-
'${selectedAssets.indexOf(asset) + 1}',
1192-
style: TextStyle(
1193-
color: selected
1194-
? theme.textTheme.bodyText1?.color
1195-
: null,
1196-
fontSize: isAppleOS ? 16.0 : 14.0,
1197-
fontWeight: isAppleOS
1198-
? FontWeight.w600
1199-
: FontWeight.bold,
1200-
),
1201-
)
1202-
: const SizedBox.shrink(),
1203-
),
1204-
),
1201+
provider.selectAsset(asset);
1202+
if (isSingleAssetMode && !isPreviewEnabled) {
1203+
Navigator.of(context).pop(provider.selectedAssets);
1204+
}
1205+
}
1206+
},
1207+
child: Container(
1208+
margin: EdgeInsets.all(
1209+
Screens.width / gridCount / (isAppleOS ? 12.0 : 15.0),
12051210
),
1211+
width: isPreviewEnabled ? indicatorSize : null,
1212+
height: isPreviewEnabled ? indicatorSize : null,
1213+
alignment: AlignmentDirectional.topEnd,
1214+
child: (!isPreviewEnabled && isSingleAssetMode && !selected)
1215+
? const SizedBox.shrink()
1216+
: innerSelector,
12061217
),
12071218
);
1219+
if (isPreviewEnabled) {
1220+
return Positioned(top: 0.0, right: 0.0, child: selectorWidget);
1221+
}
1222+
return selectorWidget;
12081223
},
12091224
);
12101225
}
@@ -1214,9 +1229,9 @@ class DefaultAssetPickerBuilderDelegate
12141229
return Positioned.fill(
12151230
child: GestureDetector(
12161231
onTap: () async {
1217-
// While the special type is WeChat moment, picture and video cannot
1232+
// When the special type is WeChat Moment, pictures and videos cannot
12181233
// be selected at the same time. Video select should be banned if any
1219-
// picture is selected.
1234+
// pictures are selected.
12201235
if (specialPickerType == SpecialPickerType.wechatMoment &&
12211236
asset.type == AssetType.video &&
12221237
provider.selectedAssets.isNotEmpty) {

lib/src/widget/asset_picker.dart

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ class AssetPicker<A, P> extends StatelessWidget {
5656
'Theme and theme color cannot be set at the same time.',
5757
);
5858
}
59-
if (specialPickerType != null && requestType != RequestType.image) {
60-
throw ArgumentError(
61-
'specialPickerType and requestType cannot be set at the same time.',
62-
);
63-
} else {
64-
if (specialPickerType == SpecialPickerType.wechatMoment) {
65-
requestType = RequestType.common;
59+
if (specialPickerType == SpecialPickerType.wechatMoment) {
60+
if (requestType != RequestType.image) {
61+
throw ArgumentError(
62+
'SpecialPickerType.wechatMoment and requestType cannot be set at the same time.',
63+
);
6664
}
65+
requestType = RequestType.common;
6766
}
6867
if ((specialItemBuilder == null &&
6968
specialItemPosition != SpecialItemPosition.none) ||

0 commit comments

Comments
 (0)