123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- part of ct_assets_picker;
-
- class ExtendedAssetPickerViewerBuilderDelegate
- extends DefaultAssetPickerViewerBuilderDelegate {
- ExtendedAssetPickerViewerBuilderDelegate({
- @required int currentIndex,
- @required List<AssetEntity> previewAssets,
- @required AssetPickerViewerProvider<AssetEntity> provider,
- @required ThemeData themeData,
- List<AssetEntity> selectedAssets,
- AssetPickerProvider<AssetEntity, AssetPathEntity> selectorProvider,
- List<int> previewThumbSize,
- SpecialPickerType specialPickerType,
- }) : super(
- currentIndex: currentIndex,
- previewAssets: previewAssets,
- provider: provider,
- themeData: themeData,
- selectedAssets: selectedAssets,
- selectorProvider: selectorProvider,
- previewThumbSize: previewThumbSize,
- specialPickerType: specialPickerType,
- );
-
- /// Whether the current platform is Apple OS.
- /// 当前平台是否为苹果系列系统
- @override
- bool get isAppleOS => false;
-
- /// [Duration] when triggering path switching.
- /// 切换路径时的动画时长
- Duration get switchingPathDuration => kThemeAnimationDuration * 1.5;
-
- /// [Curve] when triggering path switching.
- /// 切换路径时的动画曲线
- Curve get switchingPathCurve => Curves.easeInOut;
-
- /// AppBar widget.
- /// 顶栏部件
- @override
- Widget appBar(BuildContext context) {
- return AnimatedPositioned(
- duration: kThemeAnimationDuration,
- curve: Curves.easeInOut,
- top: isDisplayingDetail ? 0.0 : -(Screens.topSafeHeight + kToolbarHeight),
- left: 0.0,
- right: 0.0,
- height: Screens.topSafeHeight + kToolbarHeight,
- child: Container(
- padding: EdgeInsets.only(top: Screens.topSafeHeight, right: 12.0),
- color: themeData.canvasColor.withOpacity(0.85),
- child: Row(
- children: <Widget>[
- const BackButton(),
- if (!isAppleOS && specialPickerType == null)
- StreamBuilder<int>(
- initialData: currentIndex,
- stream: pageStreamController.stream,
- builder: (BuildContext _, AsyncSnapshot<int> snapshot) {
- if (previewAssets.isEmpty) {
- return Container();
- }
- return Text(
- '${snapshot.data + 1}/${previewAssets.length}',
- style: const TextStyle(
- fontSize: 18.0,
- fontWeight: FontWeight.bold,
- ),
- );
- },
- ),
- const Spacer(),
- if (isAppleOS && provider != null) selectButton(context),
- if (!isAppleOS && provider != null ||
- specialPickerType == SpecialPickerType.wechatMoment)
- confirmButton(context),
- ],
- ),
- ),
- );
- }
-
- /// Select button for apple OS.
- /// 苹果系列系统的选择按钮
- Widget _appleOSSelectButton(bool isSelected, AssetEntity asset) {
- return Padding(
- padding: const EdgeInsets.only(right: 10.0),
- child: GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- if (isSelected) {
- provider.unSelectAssetEntity(asset);
- } else {
- provider.selectAssetEntity(asset);
- }
- },
- child: AnimatedContainer(
- duration: kThemeAnimationDuration,
- width: 28.0,
- decoration: BoxDecoration(
- border: !isSelected
- ? Border.all(
- color: themeData.iconTheme.color,
- )
- : null,
- color: isSelected ? themeData.buttonColor : null,
- shape: BoxShape.circle,
- ),
- child: Center(
- child: isSelected
- ? Text(
- (currentIndex + 1).toString(),
- style: const TextStyle(
- fontSize: 16.0,
- fontWeight: FontWeight.bold,
- ),
- )
- : const Icon(Icons.check, size: 20.0),
- ),
- ),
- ),
- );
- }
-
- /// Select button for Android.
- /// 安卓系统的选择按钮
- Widget _androidSelectButton(bool isSelected, AssetEntity asset) {
- return RoundedCheckbox(
- value: isSelected,
- onChanged: (bool value) {
- if (isSelected) {
- provider.unSelectAssetEntity(asset);
- } else {
- provider.selectAssetEntity(asset);
- }
- },
- materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- );
- }
-
- @override
- Widget selectButton(BuildContext context) {
- return Row(
- children: <Widget>[
- StreamBuilder<int>(
- initialData: currentIndex,
- stream: pageStreamController.stream,
- builder: (BuildContext _, AsyncSnapshot<int> snapshot) {
- return ChangeNotifierProvider<
- AssetPickerViewerProvider<AssetEntity>>.value(
- value: provider,
- child: Selector<AssetPickerViewerProvider<AssetEntity>,
- List<AssetEntity>>(
- selector: (
- BuildContext _,
- AssetPickerViewerProvider<AssetEntity> provider,
- ) =>
- provider.currentlySelectedAssets,
- builder: (
- BuildContext _,
- List<AssetEntity> currentlySelectedAssets,
- Widget __,
- ) {
- final AssetEntity asset =
- previewAssets.elementAt(snapshot.data);
- final bool isSelected =
- currentlySelectedAssets.contains(asset);
- if (isAppleOS) {
- return _appleOSSelectButton(isSelected, asset);
- } else {
- return _androidSelectButton(isSelected, asset);
- }
- },
- ),
- );
- },
- ),
- if (!isAppleOS)
- Text(
- Constants.textDelegate.select,
- style: const TextStyle(fontSize: 18.0),
- ),
- ],
- );
- }
-
- /// It'll pop with [AssetPickerProvider.selectedAssets] when there're any
- /// assets chosen. The [PhotoSelector] will recognize and pop too.
- /// 当有资源已选时,点击按钮将把已选资源通过路由返回。
- /// 资源选择器将识别并一同返回。
- @override
- Widget confirmButton(BuildContext context) {
- return ChangeNotifierProvider<AssetPickerViewerProvider<AssetEntity>>.value(
- value: provider,
- child: Consumer<AssetPickerViewerProvider<AssetEntity>>(
- builder: (
- BuildContext _,
- AssetPickerViewerProvider<AssetEntity> provider,
- Widget __,
- ) {
- return FlatButton(
- minWidth: () {
- if (specialPickerType == SpecialPickerType.wechatMoment) {
- return 48.0;
- }
- return provider.isSelectedNotEmpty ? 48.0 : 20.0;
- }(),
- height: 32.0,
- padding: const EdgeInsets.symmetric(horizontal: 12.0),
- color: () {
- if (specialPickerType == SpecialPickerType.wechatMoment) {
- return themeData.colorScheme.secondary;
- }
- return provider.isSelectedNotEmpty
- ? themeData.colorScheme.primary
- : themeData.dividerColor;
- }(),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(3.0),
- ),
- child: Text(
- () {
- if (specialPickerType == SpecialPickerType.wechatMoment) {
- return Constants.textDelegate.confirm;
- }
- if (provider.isSelectedNotEmpty) {
- return '${Constants.textDelegate.confirm}'
- '(${provider.currentlySelectedAssets.length}'
- '/'
- '${selectorProvider.maxAssets})';
- }
- return Constants.textDelegate.confirm;
- }(),
- style: TextStyle(
- color: () {
- if (specialPickerType == SpecialPickerType.wechatMoment) {
- return themeData.textTheme.bodyText1.color;
- }
- return provider.isSelectedNotEmpty
- ? themeData.colorScheme.onPrimary
- : themeData.textTheme.caption.color;
- }(),
- fontSize: 17.0,
- fontWeight: FontWeight.normal,
- ),
- ),
- onPressed: () {
- if (specialPickerType == SpecialPickerType.wechatMoment) {
- Navigator.of(context).pop(<AssetEntity>[currentAsset]);
- return;
- }
- if (provider.isSelectedNotEmpty) {
- Navigator.of(context).pop(provider.currentlySelectedAssets);
- }
- },
- materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- );
- },
- ),
- );
- }
-
- /// Preview item widgets for audios.
- /// 音频的底部预览部件
- Widget _audioPreviewItem(AssetEntity asset) {
- return ColoredBox(
- color: themeData?.dividerColor,
- child: const Center(child: Icon(Icons.audiotrack)),
- );
- }
-
- /// Preview item widgets for images.
- /// 音频的底部预览部件
- Widget _imagePreviewItem(AssetEntity asset) {
- return Positioned.fill(
- child: RepaintBoundary(
- child: ExtendedImage(
- image: AssetEntityImageProvider(
- asset,
- isOriginal: false,
- ),
- fit: BoxFit.cover,
- ),
- ),
- );
- }
-
- /// Preview item widgets for video.
- /// 音频的底部预览部件
- Widget _videoPreviewItem(AssetEntity asset) {
- return Positioned.fill(
- child: Stack(
- children: <Widget>[
- _imagePreviewItem(asset),
- Center(
- child: Icon(
- Icons.video_library,
- color: themeData.colorScheme.surface.withOpacity(0.54),
- ),
- ),
- ],
- ),
- );
- }
-
- Widget fullImageButton(BuildContext context) {
- return Selector<DefaultAssetPickerProvider, bool>(
- selector: (BuildContext _, DefaultAssetPickerProvider provider) =>
- (provider as ExtendedAssetPickerProvider).fullImage,
- builder: (BuildContext _, bool fullImage, Widget __) {
- return GestureDetector(
- onTap: () {
- (selectorProvider as ExtendedAssetPickerProvider).fullImage = !fullImage;
- },
- child: Row(
- mainAxisSize: MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Container(
- // margin: EdgeInsets.all(Screens.width / gridCount / 15.0),
- width: 18,
- height: 18,
- alignment: Alignment.center,
- child: AnimatedContainer(
- duration: switchingPathDuration,
- width: 18,
- height: 18,
- decoration: BoxDecoration(
- border: Border.all(
- color: fullImage
- ? themeData.colorScheme.primary
- : themeData.unselectedWidgetColor,
- width: 2.0),
- color: null,
- shape: BoxShape.circle,
- ),
- child: AnimatedSwitcher(
- duration: switchingPathDuration,
- reverseDuration: switchingPathDuration,
- child: fullImage
- ? Container(
- width: 10,
- height: 10,
- decoration: BoxDecoration(
- color: themeData.colorScheme.primary,
- shape: BoxShape.circle,
- ),
- )
- : const SizedBox.shrink(),
- ),
- ),
- ),
- SizedBox(
- width: 8,
- ),
- Text(
- Constants.textDelegate.original,
- style: TextStyle(
- color: themeData.textTheme.caption.color,
- fontSize: 18.0,
- ),
- ),
- ],
- ),
- );
- },
- );
- }
-
- @override
- Widget bottomDetailBuilder(BuildContext context) {
- return AnimatedPositioned(
- duration: kThemeAnimationDuration,
- curve: Curves.easeInOut,
- bottom: isDisplayingDetail
- ? 0.0
- : -(Screens.bottomSafeHeight + bottomDetailHeight),
- left: 0.0,
- right: 0.0,
- height: Screens.bottomSafeHeight + bottomDetailHeight,
- child: Container(
- padding: EdgeInsets.only(bottom: Screens.bottomSafeHeight),
- color: themeData.canvasColor.withOpacity(0.85),
- child: Column(
- children: <Widget>[
- ChangeNotifierProvider<
- AssetPickerViewerProvider<AssetEntity>>.value(
- value: provider,
- child: SizedBox(
- height: 90.0,
- child: Selector<AssetPickerViewerProvider<AssetEntity>,
- List<AssetEntity>>(
- selector: (
- BuildContext _,
- AssetPickerViewerProvider<AssetEntity> provider,
- ) =>
- provider.currentlySelectedAssets,
- builder: (
- BuildContext _,
- List<AssetEntity> currentlySelectedAssets,
- Widget __,
- ) {
- return ListView.builder(
- scrollDirection: Axis.horizontal,
- padding: const EdgeInsets.symmetric(horizontal: 5.0),
- itemCount: currentlySelectedAssets.length,
- itemBuilder: bottomDetailItemBuilder,
- );
- },
- ),
- ),
- ),
- Container(
- height: 1.0,
- color: themeData.dividerColor,
- ),
- Expanded(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 20.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- // const Spacer(),
- fullImageButton(context),
- if (isAppleOS && provider != null)
- ChangeNotifierProvider<
- AssetPickerViewerProvider<AssetEntity>>.value(
- value: provider,
- child: confirmButton(context),
- )
- else
- selectButton(context),
- ],
- ),
- ),
- ),
- ],
- ),
- ),
- );
- }
-
- @override
- Widget bottomDetailItemBuilder(BuildContext context, int index) {
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
- child: AspectRatio(
- aspectRatio: 1.0,
- child: StreamBuilder<int>(
- initialData: currentIndex,
- stream: pageStreamController.stream,
- builder: (BuildContext _, AsyncSnapshot<int> snapshot) {
- final AssetEntity asset = provider.currentlySelectedAssets.elementAt(index);
- final bool isViewing = asset == currentAsset;
- return GestureDetector(
- onTap: () {
- if (!isViewing) {
- pageController.jumpToPage(previewAssets.indexWhere((e) => e.id == asset.id));
- }
- },
- child: Selector<AssetPickerViewerProvider<AssetEntity>,
- List<AssetEntity>>(
- selector: (
- BuildContext _,
- AssetPickerViewerProvider<AssetEntity> provider,
- ) =>
- provider.currentlySelectedAssets,
- builder: (
- BuildContext _,
- List<AssetEntity> currentlySelectedAssets,
- Widget __,
- ) {
- final bool isSelected =
- currentlySelectedAssets.contains(asset);
- return Stack(
- children: <Widget>[
- () {
- Widget item;
- switch (asset.type) {
- case AssetType.other:
- item = const SizedBox.shrink();
- break;
- case AssetType.image:
- item = _imagePreviewItem(asset);
- break;
- case AssetType.video:
- item = _videoPreviewItem(asset);
- break;
- case AssetType.audio:
- item = _audioPreviewItem(asset);
- break;
- }
- return item;
- }(),
- AnimatedContainer(
- duration: kThemeAnimationDuration,
- curve: Curves.easeInOut,
- decoration: BoxDecoration(
- border: isViewing
- ? Border.all(
- color: themeData.colorScheme.primary,
- width: 2.0,
- )
- : null,
- color: isSelected
- ? null
- : themeData.colorScheme.surface.withOpacity(0.54),
- ),
- ),
- ],
- );
- },
- ),
- );
- },
- ),
- ),
- );
- }
- }
|