Skip to content

Commit ada7c5d

Browse files
committed
✨ Add SpecialPickerType.
Fix #37 .
1 parent 6d28b67 commit ada7c5d

File tree

7 files changed

+136
-26
lines changed

7 files changed

+136
-26
lines changed

example/lib/pages/single_assets_page.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,23 @@ class _SingleAssetPageState extends State<SingleAssetPage> {
131131
);
132132
},
133133
),
134+
PickMethodModel(
135+
icon: '🎭',
136+
name: 'Wechat moment',
137+
description: 'Pick assets just like the wechat moment pattern.',
138+
method: (
139+
BuildContext context,
140+
List<AssetEntity> assets,
141+
) async {
142+
return await AssetPicker.pickAssets(
143+
context,
144+
maxAssets: maxAssetsCount,
145+
selectedAssets: assets,
146+
themeColor: themeColor,
147+
specialPickerType: SpecialPickerType.wechatMoment,
148+
);
149+
},
150+
),
134151
];
135152

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

lib/src/constants/constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export '../delegates/text_delegate.dart';
1111

1212
export 'colors.dart';
1313
export 'custom_scroll_physics.dart';
14+
export 'enums.dart';
1415

1516
class Constants {
1617
const Constants._();

lib/src/constants/enums.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
///
2+
/// [Author] Alex (https://github.com/AlexVincent525)
3+
/// [Date] 2020/7/8 12:32
4+
///
5+
6+
/// Provide some special picker types to integrate
7+
/// un-common pick pattern.
8+
/// 提供一些特殊的选择器类型以整合非常规的选择行为。
9+
enum SpecialPickerType { wechatMoment }

lib/src/constants/zoom_page_transition.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class _ZoomPageTransitionState extends State<ZoomPageTransition> {
119119
builder: (BuildContext context, Widget child) {
120120
if (widget.animation.status == AnimationStatus.forward ||
121121
_transitionWasInterrupted) {
122-
return Container(
122+
return ColoredBox(
123123
color:
124124
Colors.black.withOpacity(_forwardScrimOpacityAnimation.value),
125125
child: FadeTransition(

lib/src/widget/asset_picker.dart

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import 'dart:math' as math;
77
import 'dart:typed_data';
88
import 'dart:ui' as ui;
99

10-
import 'package:flutter/material.dart';
1110
import 'package:flutter/cupertino.dart';
11+
import 'package:flutter/material.dart';
1212
import 'package:flutter/services.dart';
1313
import 'package:extended_image/extended_image.dart';
1414
import 'package:photo_manager/photo_manager.dart';
@@ -28,6 +28,7 @@ class AssetPicker extends StatelessWidget {
2828
int gridCount = 4,
2929
Color themeColor,
3030
TextDelegate textDelegate,
31+
this.specialPickerType,
3132
}) : assert(
3233
provider != null,
3334
'AssetPickerProvider must be provided and not null.',
@@ -63,6 +64,17 @@ class AssetPicker extends StatelessWidget {
6364
/// 通常情况下微信选择器使用的是暗色(暗色背景)的主题,但某些情况下开发者需要亮色或自定义主题。
6465
final ThemeData pickerTheme;
6566

67+
/// The current special picker type for the viewer.
68+
/// 当前特殊选择类型
69+
///
70+
/// There're several types which are special:
71+
/// * [SpecialPickerType.wechatMoment] When user selected video, no more images
72+
/// can be selected.
73+
///
74+
/// 这里包含一些特殊选择类型:
75+
/// * [SpecialPickerType.wechatMoment] 微信朋友圈模式。当用户选择了视频,将不能选择图片。
76+
final SpecialPickerType specialPickerType;
77+
6678
/// Static method to push with the navigator.
6779
/// 跳转至选择器的静态方法
6880
static Future<List<AssetEntity>> pickAssets(
@@ -72,7 +84,8 @@ class AssetPicker extends StatelessWidget {
7284
int pageSize = 320,
7385
int pathThumbSize = 200,
7486
int gridCount = 4,
75-
RequestType requestType = RequestType.image,
87+
RequestType requestType,
88+
SpecialPickerType specialPickerType,
7689
List<AssetEntity> selectedAssets,
7790
Color themeColor,
7891
ThemeData pickerTheme,
@@ -82,15 +95,32 @@ class AssetPicker extends StatelessWidget {
8295
Duration routeDuration = const Duration(milliseconds: 300),
8396
}) async {
8497
if (maxAssets == null || maxAssets < 1) {
85-
throw ArgumentError('maxAssets must be greater than 1.');
98+
throw ArgumentError(
99+
'maxAssets must be greater than 1.',
100+
);
86101
}
87102
if (pageSize != null && pageSize % gridCount != 0) {
88-
throw ArgumentError('pageSize must be a multiple of gridCount.');
103+
throw ArgumentError(
104+
'pageSize must be a multiple of gridCount.',
105+
);
89106
}
90107
if (pickerTheme != null && themeColor != null) {
91108
throw ArgumentError(
92-
'Theme and theme color cannot be set at the same time.');
109+
'Theme and theme color cannot be set at the same time.',
110+
);
93111
}
112+
if (specialPickerType != null && requestType != null) {
113+
throw ArgumentError(
114+
'specialPickerType and requestType cannot be set at the same time.',
115+
);
116+
} else {
117+
if (specialPickerType == SpecialPickerType.wechatMoment) {
118+
requestType = RequestType.common;
119+
} else {
120+
requestType ??= RequestType.image;
121+
}
122+
}
123+
94124
try {
95125
final bool isPermissionGranted = await PhotoManager.requestPermission();
96126
if (isPermissionGranted) {
@@ -110,6 +140,7 @@ class AssetPicker extends StatelessWidget {
110140
textDelegate: textDelegate,
111141
themeColor: themeColor,
112142
pickerTheme: pickerTheme,
143+
specialPickerType: specialPickerType,
113144
);
114145
final List<AssetEntity> result = await Navigator.of(
115146
context,
@@ -272,7 +303,7 @@ class AssetPicker extends StatelessWidget {
272303
),
273304
Padding(
274305
padding: const EdgeInsets.only(left: 5.0),
275-
child: Container(
306+
child: DecoratedBox(
276307
decoration: BoxDecoration(
277308
shape: BoxShape.circle,
278309
color: theme.iconTheme.color.withOpacity(0.5),
@@ -665,13 +696,19 @@ class AssetPicker extends StatelessWidget {
665696
final bool selected = selectedAssets.contains(asset);
666697
return Positioned.fill(
667698
child: GestureDetector(
668-
onTap: () {
669-
AssetPickerViewer.pushToViewer(
699+
onTap: () async {
700+
final List<AssetEntity> result =
701+
await AssetPickerViewer.pushToViewer(
670702
context,
671703
currentIndex: index,
672704
assets: provider.currentAssets,
673705
themeData: theme,
706+
specialPickerType:
707+
asset.type == AssetType.video ? specialPickerType : null,
674708
);
709+
if (result != null) {
710+
Navigator.of(context).pop(result);
711+
}
675712
},
676713
child: AnimatedContainer(
677714
duration: switchingPathDuration,
@@ -766,7 +803,7 @@ class AssetPicker extends StatelessWidget {
766803

767804
/// [GridView] for assets under [AssetPickerProvider.currentPathEntity].
768805
/// 正在查看的目录下的资源网格部件
769-
Widget assetsGrid(BuildContext context) => Container(
806+
Widget assetsGrid(BuildContext context) => ColoredBox(
770807
color: theme.canvasColor,
771808
child: Selector<AssetPickerProvider, List<AssetEntity>>(
772809
selector: (BuildContext _, AssetPickerProvider provider) =>
@@ -811,7 +848,9 @@ class AssetPicker extends StatelessWidget {
811848
return Stack(
812849
children: <Widget>[
813850
builder,
814-
_selectIndicator(asset),
851+
if (specialPickerType != SpecialPickerType.wechatMoment ||
852+
asset.type != AssetType.video)
853+
_selectIndicator(asset),
815854
],
816855
);
817856
},
@@ -876,7 +915,7 @@ class AssetPicker extends StatelessWidget {
876915
Widget loader;
877916
switch (state.extendedImageLoadState) {
878917
case LoadState.loading:
879-
loader = Container(color: const Color(0x10ffffff));
918+
loader = const ColoredBox(color: Color(0x10ffffff));
880919
break;
881920
case LoadState.completed:
882921
SpecialImageType type;

lib/src/widget/asset_picker_viewer.dart

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class AssetPickerViewer extends StatefulWidget {
3030
@required this.themeData,
3131
this.selectedAssets,
3232
this.selectorProvider,
33+
this.specialPickerType,
3334
}) : super(key: key);
3435

3536
/// Current previewing index in assets.
@@ -52,6 +53,13 @@ class AssetPickerViewer extends StatefulWidget {
5253
/// 主题
5354
final ThemeData themeData;
5455

56+
/// The current special picker type for the viewer.
57+
/// 当前特殊选择类型
58+
///
59+
/// If the type is not null, the title of the viewer will not display.
60+
/// 如果类型不为空,则标题将不会显示。
61+
final SpecialPickerType specialPickerType;
62+
5563
@override
5664
AssetPickerViewerState createState() => AssetPickerViewerState();
5765

@@ -64,6 +72,7 @@ class AssetPickerViewer extends StatefulWidget {
6472
@required ThemeData themeData,
6573
List<AssetEntity> selectedAssets,
6674
AssetPickerProvider selectorProvider,
75+
SpecialPickerType specialPickerType,
6776
}) async {
6877
try {
6978
final Widget viewer = AssetPickerViewer(
@@ -72,6 +81,7 @@ class AssetPickerViewer extends StatefulWidget {
7281
themeData: themeData,
7382
selectedAssets: selectedAssets,
7483
selectorProvider: selectorProvider,
84+
specialPickerType: specialPickerType,
7585
);
7686
final PageRouteBuilder<List<AssetEntity>> pageRoute =
7787
PageRouteBuilder<List<AssetEntity>>(
@@ -302,7 +312,7 @@ class AssetPickerViewerState extends State<AssetPickerViewer>
302312
child: Row(
303313
children: <Widget>[
304314
const BackButton(),
305-
if (!isAppleOS)
315+
if (!isAppleOS && widget.specialPickerType == null)
306316
StreamBuilder<int>(
307317
initialData: currentIndex,
308318
stream: pageStreamController.stream,
@@ -318,7 +328,9 @@ class AssetPickerViewerState extends State<AssetPickerViewer>
318328
),
319329
const Spacer(),
320330
if (isAppleOS && provider != null) selectButton,
321-
if (!isAppleOS && provider != null) confirmButton(context),
331+
if (!isAppleOS && provider != null ||
332+
widget.specialPickerType == SpecialPickerType.wechatMoment)
333+
confirmButton(context),
322334
],
323335
),
324336
),
@@ -341,30 +353,61 @@ class AssetPickerViewerState extends State<AssetPickerViewer>
341353
Widget __,
342354
) {
343355
return MaterialButton(
344-
minWidth: provider.isSelectedNotEmpty ? 48.0 : 20.0,
356+
minWidth: () {
357+
if (widget.specialPickerType ==
358+
SpecialPickerType.wechatMoment) {
359+
return 48.0;
360+
}
361+
return provider.isSelectedNotEmpty ? 48.0 : 20.0;
362+
}(),
345363
height: 32.0,
346364
padding: const EdgeInsets.symmetric(horizontal: 12.0),
347-
color: provider.isSelectedNotEmpty
348-
? widget.themeData.colorScheme.secondary
349-
: widget.themeData.dividerColor,
365+
color: () {
366+
if (widget.specialPickerType ==
367+
SpecialPickerType.wechatMoment) {
368+
return widget.themeData.colorScheme.secondary;
369+
}
370+
return provider.isSelectedNotEmpty
371+
? widget.themeData.colorScheme.secondary
372+
: widget.themeData.dividerColor;
373+
}(),
350374
shape: RoundedRectangleBorder(
351375
borderRadius: BorderRadius.circular(3.0),
352376
),
353377
child: Text(
354-
provider.isSelectedNotEmpty
355-
? '${Constants.textDelegate.confirm}(${provider.currentlySelectedAssets.length}'
378+
() {
379+
if (widget.specialPickerType ==
380+
SpecialPickerType.wechatMoment) {
381+
return Constants.textDelegate.confirm;
382+
}
383+
if (provider.isSelectedNotEmpty) {
384+
return '${Constants.textDelegate.confirm}'
385+
'(${provider.currentlySelectedAssets.length}'
356386
'/'
357-
'${widget.selectorProvider.maxAssets})'
358-
: Constants.textDelegate.confirm,
387+
'${widget.selectorProvider.maxAssets})';
388+
}
389+
return Constants.textDelegate.confirm;
390+
}(),
359391
style: TextStyle(
360-
color: provider.isSelectedNotEmpty
361-
? widget.themeData.textTheme.bodyText1.color
362-
: widget.themeData.textTheme.caption.color,
392+
color: () {
393+
if (widget.specialPickerType ==
394+
SpecialPickerType.wechatMoment) {
395+
return widget.themeData.textTheme.bodyText1.color;
396+
}
397+
return provider.isSelectedNotEmpty
398+
? widget.themeData.textTheme.bodyText1.color
399+
: widget.themeData.textTheme.caption.color;
400+
}(),
363401
fontSize: 17.0,
364402
fontWeight: FontWeight.normal,
365403
),
366404
),
367405
onPressed: () {
406+
if (widget.specialPickerType ==
407+
SpecialPickerType.wechatMoment) {
408+
Navigator.of(context).pop(<AssetEntity>[currentAsset]);
409+
return;
410+
}
368411
if (provider.isSelectedNotEmpty) {
369412
Navigator.of(context).pop(provider.currentlySelectedAssets);
370413
}

lib/wechat_assets_picker.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
library wechat_assets_picker;
22

33
export 'package:photo_manager/photo_manager.dart'
4-
show AssetEntity, RequestType, AssetType;
4+
show AssetEntity, AssetType, RequestType;
55

6+
export 'src/constants/enums.dart';
67
export 'src/delegates/sort_path_delegate.dart';
78
export 'src/delegates/text_delegate.dart';
89
export 'src/provider/asset_entity_image_provider.dart';

0 commit comments

Comments
 (0)