|
- import 'dart:async';
- import 'dart:typed_data';
-
- import 'package:chat/generated/i18n.dart';
- import 'package:chat/photo/delegate/loading_delegate.dart';
- import 'package:chat/photo/engine/lru_cache.dart';
- import 'package:chat/photo/engine/throttle.dart';
- import 'package:chat/photo/entity/options.dart';
- import 'package:chat/photo/provider/asset_provider.dart';
- import 'package:chat/photo/provider/config_provider.dart';
- import 'package:chat/photo/provider/selected_provider.dart';
- import 'package:chat/photo/ui/page/photo_folder_select_menu.dart';
- import 'package:chat/photo/ui/page/photo_preview_page.dart';
- import 'package:chat/utils/screen.dart';
- import 'package:flutter/material.dart';
- import 'package:photo_manager/photo_manager.dart';
-
- part './bottom_widget.dart';
- part './image_item.dart';
-
- class PhotoMainPage extends StatefulWidget {
- final ValueChanged<List<AssetEntity>> onClose;
- final Options options;
- final List<AssetPathEntity> photoList;
-
- const PhotoMainPage({
- Key key,
- this.onClose,
- this.options,
- this.photoList,
- }) : super(key: key);
-
- @override
- _PhotoMainPageState createState() => _PhotoMainPageState();
- }
-
- class _PhotoMainPageState extends State<PhotoMainPage> with SelectedProvider {
- Options get options => widget.options;
-
- AssetProvider get assetProvider =>
- PhotoPickerProvider.of(context).assetProvider;
-
- List<AssetEntity> get list => assetProvider.data;
-
- Color get themeColor => options.themeColor;
-
- AssetPathEntity _currentPath;
-
- bool _isInit = false;
-
- AssetPathEntity get currentPath {
- if (_currentPath == null) {
- return null;
- }
- return _currentPath;
- }
-
- set currentPath(AssetPathEntity value) {
- _currentPath = value;
- }
-
- String get currentGalleryName {
- if (currentPath?.isAll == true) {
- return I18n.of(context).all_photo;
- }
- return currentPath?.name ?? "Select Folder";
- }
-
- GlobalKey scaffoldKey;
- ScrollController scrollController;
-
- bool isPushed = false;
-
- bool get useAlbum => widget.photoList == null || widget.photoList.isEmpty;
-
- Throttle _changeThrottle;
-
- var appBarKey = GlobalKey();
- OverlayEntry overlayEntry;
-
- bool isQuit = false;
-
- @override
- void initState() {
- super.initState();
-
- scaffoldKey = GlobalKey();
- scrollController = ScrollController();
- _changeThrottle = Throttle(onCall: _onAssetChange);
- PhotoManager.addChangeCallback(_changeThrottle.call);
- PhotoManager.startChangeNotify();
- _refreshListFromGallery();
- }
-
- @override
- void dispose() {
- PhotoManager.removeChangeCallback(_changeThrottle.call);
- PhotoManager.stopChangeNotify();
- _changeThrottle.dispose();
- scaffoldKey = null;
- appBarKey = null;
-
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- var textStyle = TextStyle(
- color: options.textColor,
- fontSize: 14.0,
- );
- return Theme(
- data: Theme.of(context).copyWith(primaryColor: options.themeColor),
- child: DefaultTextStyle(
- style: textStyle,
- child: Scaffold(
- backgroundColor: Color(0xFFF0F0F0),
- appBar: AppBar(
- elevation: 1.0,
- key: appBarKey,
- backgroundColor: Colors.white,
- leading: IconButton(
- icon: fixedText(
- I18n.of(context).cancel,
- color: options.textColor,
- ),
- onPressed: _cancel,
- ),
- title: PhotoSelectMenu(
- parentKey: appBarKey, onSelectFolder: _onGalleryChange),
- centerTitle: true,
- actions: <Widget>[
- Center(
- child:Padding(padding: EdgeInsets.only(right:16),child: fixedText('$selectedCount/${options.maxSelected}',color: Colors.blue,fontSize: 16))
- )
- ],
- ),
- body: _buildBody(),
- bottomNavigationBar: _BottomWidget(
- key: scaffoldKey,
- options: options,
- galleryName: currentGalleryName,
- onSend: selectedList.isEmpty ? null : sure,
- onTapPreview: selectedList.isEmpty ? null : _onTapPreview,
- selectedProvider: this,
- ),
- ),
- ),
- );
- }
-
- void _cancel() {
- selectedList.clear();
- widget.onClose(selectedList);
- }
-
- @override
- bool isUpperLimit() {
- var result = selectedCount == options.maxSelected;
- if (result)
- _showTip(I18n.of(context)
- .have_select
- .replaceFirst('/s1', options.maxSelected.toString()));
- return result;
- }
-
- void sure() {
- widget.onClose?.call(selectedList);
- }
-
- void _showTip(String msg) {
- if (isPushed) {
- return;
- }
- Scaffold.of(scaffoldKey.currentContext).showSnackBar(
- SnackBar(
- content: Text(
- msg,
- style: TextStyle(
- color: options.textColor,
- fontSize: 15.0,
- ),
- ),
- duration: Duration(milliseconds: 1500),
- backgroundColor: themeColor.withOpacity(0.8),
- ),
- );
- }
-
- Future<void> _refreshListFromGallery() async {
- List<AssetPathEntity> pathList;
- switch (options.pickType) {
- case PickType.onlyImage:
- pathList = await PhotoManager.getAssetPathList(type: RequestType.image);
- break;
- case PickType.onlyVideo:
- pathList = await PhotoManager.getAssetPathList(type: RequestType.video);
- break;
- default:
- pathList = await PhotoManager.getAssetPathList();
- }
-
- if (pathList == null) {
- return;
- }
-
- options.sortDelegate.sort(pathList);
-
- if (pathList.isNotEmpty) {
- assetProvider.current = pathList[0];
- await assetProvider.loadMore();
- }
-
- for (var path in pathList) {
- if (path.isAll) {
- path.name = I18n.of(context).all_photo;
- }
- }
- setState(() {
- _isInit = true;
- });
- }
-
- Widget _buildBody() {
- if (!_isInit) {
- return Center(
- child: CircularProgressIndicator(
- valueColor: AlwaysStoppedAnimation(themeColor),
- ));
- }
-
- final noMore = assetProvider.noMore;
-
- final count = assetProvider.count + (noMore ? 0 : 1);
- if (list.length == 0) {
- print('图片数目为空');
- _refreshListFromGallery();
- return Center(
- child: CircularProgressIndicator(
- valueColor: AlwaysStoppedAnimation(themeColor),
- ));
- }
- print('图片数目${list.length}');
- return Container(
- color: options.dividerColor,
- child: GridView.builder(
- controller: scrollController,
- gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: options.rowCount,
- childAspectRatio: options.itemRadio,
- crossAxisSpacing: options.padding,
- mainAxisSpacing: options.padding,
- ),
- itemBuilder: _buildItem,
- itemCount: count,
- ),
- );
- }
-
- Widget _buildItem(BuildContext context, int index) {
- final noMore = assetProvider.noMore;
- if (!noMore && index == assetProvider.count) {
- _loadMore();
- return _buildLoading();
- }
-
- var data = list[index];
- return RepaintBoundary(
- child: GestureDetector(
- onTap: () => _onItemClick(data, index),
- child: Stack(
- children: <Widget>[
- ImageItem(
- entity: data,
- themeColor: themeColor,
- size: options.thumbSize,
- loadingDelegate: options.loadingDelegate,
- ),
- _buildMask(containsEntity(data)),
- _buildSelected(data),
- ],
- ),
- ),
- );
- }
-
- _loadMore() async {
- await assetProvider.loadMore();
- setState(() {});
- }
-
- _buildMask(bool showMask) {
- return IgnorePointer(
- child: AnimatedContainer(
- color: showMask ? Colors.black.withOpacity(0.5) : Colors.transparent,
- duration: Duration(milliseconds: 300),
- ),
- );
- }
-
- Widget _buildSelected(AssetEntity entity) {
- var currentSelected = containsEntity(entity);
- return Positioned(
- right: 0.0,
- width: 40.0,
- height: 40.0,
- child: GestureDetector(
- onTap: () {
- changeCheck(!currentSelected, entity);
- },
- behavior: HitTestBehavior.translucent,
- child: _buildText(entity),
- ),
- );
- }
-
- Widget _buildText(AssetEntity entity) {
- var isSelected = containsEntity(entity);
- Widget child;
- BoxDecoration decoration;
- if (isSelected) {
- child = Text(
- (indexOfSelected(entity) + 1).toString(),
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 12.0,
- color: Colors.white,
- ),
- );
- decoration = BoxDecoration(
- color: Color(0xFF2D81FF),
- shape: BoxShape.circle,
- border: Border.all(
- color: Colors.white30,
- ),
- );
- } else {
- decoration = BoxDecoration(
- shape: BoxShape.circle,
- border: Border.all(
- color: themeColor,
- ),
- boxShadow: [BoxShadow(color: Colors.black38)],
- color: Colors.white24);
- }
- return Padding(
- padding: const EdgeInsets.all(8.0),
- child: AnimatedContainer(
- duration: Duration(milliseconds: 300),
- decoration: decoration,
- alignment: Alignment.center,
- child: child,
- ),
- );
- }
-
- void changeCheck(bool value, AssetEntity entity) {
- if (value) {
- addSelectEntity(entity);
- } else {
- removeSelectEntity(entity);
- }
- setState(() {});
- }
-
- void _onGalleryChange(AssetPathEntity assetPathEntity) async {
- if (assetPathEntity != assetProvider.current) {
- assetProvider.current = assetPathEntity;
- await assetProvider.loadMore();
- setState(() {});
- }
- }
-
- void _onItemClick(AssetEntity data, int index) {
- var result = new PhotoPreviewResult();
- isPushed = true;
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (ctx) {
- return PhotoPickerProvider(
- options: options,
- child: PhotoPreviewPage(
- selectedProvider: this,
- list: List.of(list),
- initIndex: index,
- changeProviderOnCheckChange: true,
- result: result,
- isPreview: false,
- assetProvider: assetProvider,
- ),
- );
- },
- ),
- ).then((v) {
- if (handlePreviewResult(v)) {
- Navigator.pop(context, v);
- return;
- }
- isPushed = false;
- setState(() {});
- });
- }
-
- void _onTapPreview() async {
- var result = new PhotoPreviewResult();
- isPushed = true;
- var v = await Navigator.of(context).push(
- MaterialPageRoute(
- builder: (ctx) => PhotoPickerProvider(
- options: options,
- child: PhotoPreviewPage(
- selectedProvider: this,
- list: List.of(selectedList),
- changeProviderOnCheckChange: false,
- result: result,
- isPreview: true,
- assetProvider: assetProvider,
- ),
- ),
- ),
- );
- if (handlePreviewResult(v)) {
- // print(v);
- Navigator.pop(context, v);
- return;
- }
- isPushed = false;
- compareAndRemoveEntities(result.previewSelectedList);
- }
-
- bool handlePreviewResult(List<AssetEntity> v) {
- if (v == null) {
- return false;
- }
- if (v is List<AssetEntity>) {
- return true;
- }
- return false;
- }
-
- Widget _buildLoading() {
- return Center(
- child: Column(
- children: <Widget>[
- Container(
- width: 40.0,
- height: 40.0,
- padding: const EdgeInsets.all(5.0),
- child: CircularProgressIndicator(
- valueColor: AlwaysStoppedAnimation(themeColor),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Text(
- I18n.of(context).loading,
- style: const TextStyle(
- fontSize: 12.0,
- ),
- ),
- ),
- ],
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- ),
- );
- }
-
- void _onAssetChange() {
- if (useAlbum) {
- _onPhotoRefresh();
- }
- }
-
- void _onPhotoRefresh() async {
- List<AssetPathEntity> pathList;
- switch (options.pickType) {
- case PickType.onlyImage:
- pathList = await PhotoManager.getAssetPathList(type: RequestType.image);
- break;
- case PickType.onlyVideo:
- pathList = await PhotoManager.getAssetPathList(type: RequestType.video);
- break;
- default:
- pathList = await PhotoManager.getAssetPathList();
- }
-
- if (pathList == null) {
- return;
- }
-
- // Not deleted
- _onGalleryChange(this.currentPath);
- }
- }
|