wechat_assets_picker 2.2.0-dev.2 wechat_assets_picker: ^2.2.0-dev.2 copied to clipboard
An assets picker in pure dart which looks like the one in WeChat, support multi asset pick from device.
///
/// [Author] Alex (https://github.com/AlexVincent525)
/// [Date] 2020/5/30 15:39
///
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_common_exports/flutter_common_exports.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'constants/picker_model.dart';
import 'constants/resource.dart';
const Color themeColor = Color(0xff00bc56);
bool get currentIsDark => Screens.mediaQuery.platformBrightness.isDark;
void main() {
runApp(MyApp());
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.transparent,
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WeChat Asset Picker Demo',
theme: ThemeData(
brightness: Screens.mediaQuery.platformBrightness,
primarySwatch: themeColor.swatch,
cursorColor: themeColor,
),
home: const MyHomePage(),
builder: (BuildContext c, Widget w) {
return ScrollConfiguration(
behavior: const NoGlowScrollBehavior(),
child: w,
);
},
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final int maxAssetsCount = 9;
List<AssetEntity> assets = <AssetEntity>[];
int get assetsLength => assets.length;
ThemeData get currentTheme => context.themeData;
bool isDisplayingDetail = true;
List<PickMethodModel> get pickMethods => <PickMethodModel>[
PickMethodModel(
icon: '๐ผ๏ธ',
name: 'Image picker',
description: 'Simply pick image from device.',
method: (
BuildContext context,
List<AssetEntity> assets,
) async {
return await AssetPicker.pickAssets(
context,
maxAssets: 9,
pathThumbSize: 84,
gridCount: 4,
selectedAssets: assets,
themeColor: themeColor,
requestType: RequestType.image,
);
},
),
PickMethodModel(
icon: '๐',
name: 'Video picker',
description: 'Simply pick video from device.',
method: (
BuildContext context,
List<AssetEntity> assets,
) async {
return await AssetPicker.pickAssets(
context,
maxAssets: 9,
pathThumbSize: 84,
gridCount: 4,
selectedAssets: assets,
themeColor: themeColor,
requestType: RequestType.video,
);
},
),
PickMethodModel(
icon: '๐ถ',
name: 'Audio picker',
description: 'Simply pick audio from device.',
method: (
BuildContext context,
List<AssetEntity> assets,
) async {
return await AssetPicker.pickAssets(
context,
maxAssets: 9,
pathThumbSize: 84,
gridCount: 4,
selectedAssets: assets,
themeColor: themeColor,
requestType: RequestType.video,
);
},
),
];
Future<void> selectAssets(PickMethodModel model) async {
final List<AssetEntity> result = await model.method(context, assets);
if (result != null) {
assets = List<AssetEntity>.from(result);
if (mounted) {
setState(() {});
}
}
}
Future<void> methodWrapper(PickMethodModel model) async {
assets = List<AssetEntity>.from(
await model.method(context, assets),
);
if (mounted) {
setState(() {});
}
}
void removeAsset(int index) {
setState(() {
assets.remove(assets.elementAt(index));
if (assets.isEmpty) {
isDisplayingDetail = false;
}
});
}
Widget get header => Container(
margin: const EdgeInsets.only(top: 30.0),
height: 60.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AspectRatio(
aspectRatio: 1.0,
child: Image.asset(R.ASSETS_FLUTTER_CANDIES_LOGO_PNG),
),
const SizedBox(width: 10.0),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'WeChat Asset Picker',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
Text(
'Demo for the package.',
style: context.themeData.textTheme.caption,
),
],
),
const SizedBox(width: 20.0),
],
),
);
/// Selected asset image widget.
/// ๅทฒ้่ตๆบ็ๅไธชๅพ็็ปไปถ
Widget _selectedAssetWidget(int index) {
final AssetEntity asset = assets.elementAt(index);
return GestureDetector(
onTap: isDisplayingDetail
? () async {
final List<AssetEntity> result = await AssetPickerViewer.pushToViewer(
context,
currentIndex: index,
assets: assets,
themeData: AssetPicker.themeData(themeColor),
);
if (result != assets && result != null) {
assets = List<AssetEntity>.from(result);
if (mounted) {
setState(() {});
}
}
}
: null,
child: RepaintBoundary(
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image(
image: AssetEntityImageProvider(asset, isOriginal: false),
fit: BoxFit.cover,
),
),
),
);
}
/// Delete button for asset.
/// ่ตๆบ็ๅ ้คๆ้ฎ
Widget _selectedAssetDeleteButton(int index) {
return GestureDetector(
onTap: () {
setState(() {
assets.remove(assets.elementAt(index));
if (assetsLength == 0) {
isDisplayingDetail = false;
}
});
},
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
color: currentTheme.canvasColor.withOpacity(0.5),
),
child: Icon(
Icons.close,
color: currentTheme.iconTheme.color,
size: 18.0,
),
),
);
}
Widget methodItemBuilder(BuildContext _, int index) {
final PickMethodModel model = pickMethods[index];
return InkWell(
onTap: () async {
final List<AssetEntity> result = await model.method(context, assets);
if (result != null && result != assets) {
assets = List<AssetEntity>.from(result);
if (mounted) {
setState(() {});
}
}
},
child: Container(
height: 72.0,
padding: const EdgeInsets.symmetric(
horizontal: 30.0,
vertical: 10.0,
),
child: Row(
children: <Widget>[
AspectRatio(
aspectRatio: 1.0,
child: Container(
margin: const EdgeInsets.all(2.0),
child: Center(
child: Text(
model.icon,
style: const TextStyle(fontSize: 24.0),
),
),
),
),
const SizedBox(width: 12.0),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
model.name,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
Text(
model.description,
style: context.themeData.textTheme.caption,
),
],
),
),
Icon(
Icons.chevron_right,
color: Colors.grey,
),
],
),
),
);
}
Widget get methodListView => Expanded(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 10.0),
itemCount: pickMethods.length,
itemBuilder: methodItemBuilder,
),
);
Widget get selectedAssetsWidget => AnimatedContainer(
duration: kThemeChangeDuration,
curve: Curves.easeInOut,
height: assets.isNotEmpty ? isDisplayingDetail ? 120.0 : 80.0 : 40.0,
child: Column(
children: <Widget>[
SizedBox(
height: 20.0,
child: GestureDetector(
onTap: () {
if (assets.isNotEmpty) {
setState(() {
isDisplayingDetail = !isDisplayingDetail;
});
}
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text('Selected Assets'),
const SizedBox(width: 10.0),
Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey,
),
child: Text(
'${assets.length}',
style: TextStyle(
color: Colors.white,
height: 1.0,
),
),
),
if (assets.isNotEmpty)
Icon(
isDisplayingDetail ? Icons.keyboard_arrow_down : Icons.keyboard_arrow_up,
),
],
),
),
),
selectedAssetsListView,
],
),
);
Widget get selectedAssetsListView => Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 8.0),
scrollDirection: Axis.horizontal,
itemCount: assetsLength,
itemBuilder: (BuildContext _, int index) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 16.0,
),
child: AspectRatio(
aspectRatio: 1.0,
child: Stack(
children: <Widget>[
Positioned.fill(child: _selectedAssetWidget(index)),
AnimatedPositioned(
duration: kThemeAnimationDuration,
top: isDisplayingDetail ? 6.0 : -30.0,
right: isDisplayingDetail ? 6.0 : -30.0,
child: _selectedAssetDeleteButton(index),
),
],
),
),
);
},
),
);
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: Screens.mediaQuery.platformBrightness.isDark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark,
child: Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
header,
methodListView,
selectedAssetsWidget,
],
),
),
),
);
}
}