Skip to content

Commit 5225eae

Browse files
authored
✨ Explicit Live Photos indicator for assets (#629)
1 parent f63a0e5 commit 5225eae

11 files changed

+190
-86
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ that can be found in the LICENSE file. -->
99
1010
## Unreleased
1111

12+
### New features
13+
14+
- Add explicit Live Photos indicator for assets.
15+
1216
### Fixes
1317

1418
- Fix bottom actions bar display conditions.

README-ZH.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Language: [English](README.md) | 中文
2020

2121
基于 **微信 UI** 的 Flutter **图片选择器(同时支持视频和音频)**
2222

23-
当前的界面设计基于的微信版本:**8.3.x**
23+
当前的界面设计基于的微信版本:**8.0.51**
2424
界面更新将在微信版本更新后随时进行跟进。
2525

2626
如果你需要拍照及录制视频,请先查看示例的详细用法,

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Language: English | [中文](README-ZH.md)
2121
An **image picker (also with videos and audios)**
2222
for Flutter projects based on the WeChat's UI.
2323

24-
Current WeChat version that UI based on: **8.3.x**
24+
Current WeChat version that UI based on: **8.0.51**
2525
UI designs will be updated following the WeChat update in anytime.
2626

2727
To take a photo or a video for assets,

assets/icon/indicator-live-photos.png

5.84 KB
Loading

lib/src/delegates/asset_picker_builder_delegate.dart

+38-12
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
405405
/// GIF image type indicator.
406406
/// GIF 类型图片指示
407407
Widget gifIndicator(BuildContext context, Asset asset) {
408-
return Positioned.fill(
409-
top: null,
408+
return Align(
409+
alignment: Alignment.bottomCenter,
410410
child: Container(
411411
alignment: AlignmentDirectional.centerEnd,
412412
padding: const EdgeInsets.all(6),
@@ -442,6 +442,34 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
442442
);
443443
}
444444

445+
Widget buildLivePhotoIndicator(BuildContext context, Asset asset) {
446+
return Align(
447+
alignment: AlignmentDirectional.bottomCenter,
448+
child: Container(
449+
width: double.maxFinite,
450+
height: 26,
451+
alignment: AlignmentDirectional.bottomStart,
452+
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 2),
453+
decoration: BoxDecoration(
454+
gradient: LinearGradient(
455+
begin: AlignmentDirectional.bottomCenter,
456+
end: AlignmentDirectional.topCenter,
457+
colors: <Color>[
458+
theme.canvasColor.withAlpha(80),
459+
Colors.transparent,
460+
],
461+
),
462+
),
463+
child: Image.asset(
464+
'assets/icon/indicator-live-photos.png',
465+
package: packageName,
466+
gaplessPlayback: true,
467+
color: Colors.white,
468+
),
469+
),
470+
);
471+
}
472+
445473
/// Indicator when the asset cannot be selected.
446474
/// 当资源无法被选中时的遮罩
447475
Widget itemBannedIndicator(BuildContext context, Asset asset) {
@@ -1700,19 +1728,19 @@ class DefaultAssetPickerBuilderDelegate
17001728
type = SpecialImageType.heic;
17011729
}
17021730
return Stack(
1731+
fit: StackFit.expand,
17031732
children: <Widget>[
1704-
Positioned.fill(
1705-
child: RepaintBoundary(
1706-
child: AssetEntityGridItemBuilder(
1707-
image: imageProvider,
1708-
failedItemBuilder: failedItemBuilder,
1709-
),
1733+
RepaintBoundary(
1734+
child: AssetEntityGridItemBuilder(
1735+
image: imageProvider,
1736+
failedItemBuilder: failedItemBuilder,
17101737
),
17111738
),
17121739
if (type == SpecialImageType.gif) // 如果为GIF则显示标识
17131740
gifIndicator(context, asset),
17141741
if (asset.type == AssetType.video) // 如果为视频则显示标识
17151742
videoIndicator(context, asset),
1743+
if (asset.isLivePhoto) buildLivePhotoIndicator(context, asset),
17161744
],
17171745
);
17181746
},
@@ -2260,10 +2288,8 @@ class DefaultAssetPickerBuilderDelegate
22602288
/// 将指示器的图标和文字设置为 [Colors.white]
22612289
@override
22622290
Widget videoIndicator(BuildContext context, AssetEntity asset) {
2263-
return PositionedDirectional(
2264-
start: 0,
2265-
end: 0,
2266-
bottom: 0,
2291+
return Align(
2292+
alignment: Alignment.bottomCenter,
22672293
child: Container(
22682294
width: double.maxFinite,
22692295
height: 26,

lib/src/delegates/asset_picker_text_delegate.dart

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class AssetPickerTextDelegate {
6060
/// GIF指示的字段
6161
String get gifIndicator => 'GIF';
6262

63+
/// Live-Photo image indicator string.
64+
/// 实况图片指示的字段
65+
String get livePhotoIndicator => '实况';
66+
6367
/// Load failed string for item.
6468
/// 资源加载失败时的字段
6569
String get loadFailed => '加载失败';
@@ -182,6 +186,9 @@ class EnglishAssetPickerTextDelegate extends AssetPickerTextDelegate {
182186
@override
183187
String get gifIndicator => 'GIF';
184188

189+
@override
190+
String get livePhotoIndicator => 'LIVE';
191+
185192
@override
186193
String get loadFailed => 'Load failed';
187194

lib/src/widget/asset_picker.dart

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'dart:io';
88
import 'package:flutter/material.dart';
99
import 'package:flutter/services.dart';
1010
import 'package:photo_manager/photo_manager.dart';
11+
import 'package:wechat_picker_library/wechat_picker_library.dart';
1112

1213
import '../constants/config.dart';
1314
import '../delegates/asset_picker_builder_delegate.dart';
@@ -144,9 +145,7 @@ class AssetPickerState<Asset, Path> extends State<AssetPicker<Asset, Path>>
144145
Future<void> _onAssetsUpdated(MethodCall call) {
145146
return widget.builder.onAssetsChanged(call, (VoidCallback fn) {
146147
fn();
147-
if (mounted) {
148-
setState(() {});
149-
}
148+
safeSetState(() {});
150149
});
151150
}
152151

lib/src/widget/builder/audio_page_builder.dart

+2-6
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,7 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
114114
);
115115
} finally {
116116
isLoaded = true;
117-
if (mounted) {
118-
setState(() {});
119-
}
117+
safeSetState(() {});
120118
}
121119
}
122120

@@ -125,9 +123,7 @@ class _AudioPageBuilderState extends State<AudioPageBuilder> {
125123
void audioPlayerListener() {
126124
if (isControllerPlaying != isPlaying) {
127125
isPlaying = isControllerPlaying;
128-
if (mounted) {
129-
setState(() {});
130-
}
126+
safeSetState(() {});
131127
}
132128

133129
/// Add the current position into the stream.

0 commit comments

Comments
 (0)