123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- import 'dart:async';
- import 'dart:typed_data';
-
- import 'package:flutter/material.dart';
- import 'package:photo/src/entity/options.dart';
- import 'package:photo/src/provider/config_provider.dart';
- import 'package:photo/src/provider/selected_provider.dart';
- import 'package:photo/src/ui/page/photo_main_page.dart';
- import 'package:photo_manager/photo_manager.dart';
-
- class PhotoPreviewPage extends StatefulWidget {
- final SelectedProvider selectedProvider;
-
- final List<AssetEntity> list;
-
- final int initIndex;
-
- /// 这个参数是控制在内部点击check后是否实时修改provider状态
- final bool changeProviderOnCheckChange;
-
- /// 这里封装了结果
- final PhotoPreviewResult result;
-
- const PhotoPreviewPage({
- Key key,
- @required this.selectedProvider,
- @required this.list,
- @required this.changeProviderOnCheckChange,
- @required this.result,
- this.initIndex = 0,
- }) : super(key: key);
-
- @override
- _PhotoPreviewPageState createState() => _PhotoPreviewPageState();
- }
-
- class _PhotoPreviewPageState extends State<PhotoPreviewPage> {
- ConfigProvider get config => ConfigProvider.of(context);
-
- Options get options => config.options;
-
- Color get themeColor => options.themeColor;
-
- Color get textColor => options.textColor;
-
- SelectedProvider get selectedProvider => widget.selectedProvider;
-
- List<AssetEntity> get list => widget.list;
-
- StreamController<int> pageChangeController = StreamController.broadcast();
-
- Stream<int> get pageStream => pageChangeController.stream;
-
- bool get changeProviderOnCheckChange => widget.changeProviderOnCheckChange;
-
- PhotoPreviewResult get result => widget.result;
-
- /// 缩略图用的数据
- ///
- /// 用于与provider数据联动
- List<AssetEntity> get previewList {
- return selectedProvider.selectedList;
- }
-
- /// 选中的数据
- List<AssetEntity> _selectedList = [];
-
- List<AssetEntity> get selectedList {
- if (changeProviderOnCheckChange) {
- return previewList;
- }
- return _selectedList;
- }
-
- PageController pageController;
-
- @override
- void initState() {
- super.initState();
- pageChangeController.add(0);
- pageController = PageController(
- initialPage: widget.initIndex,
- );
-
- _selectedList.clear();
- _selectedList.addAll(selectedProvider.selectedList);
-
- result.previewSelectedList = _selectedList;
- }
-
- @override
- void dispose() {
- pageChangeController.close();
- 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: Scaffold(
- appBar: AppBar(
- backgroundColor: config.options.themeColor,
- title: StreamBuilder(
- stream: pageStream,
- initialData: widget.initIndex,
- builder: (ctx, snap) => Text(
- "${snap.data + 1}/${widget.list.length}",
- ),
- ),
- actions: <Widget>[
- StreamBuilder(
- stream: pageStream,
- builder: (ctx, s) => FlatButton(
- splashColor: Colors.transparent,
- onPressed: selectedList.length == 0 ? null : sure,
- child: Text(
- config.provider.getSureText(options, selectedList.length),
- style: selectedList.length == 0
- ? textStyle.copyWith(color: options.disableColor)
- : textStyle,
- ),
- ),
- ),
- ],
- ),
- body: PageView.builder(
- controller: pageController,
- itemBuilder: _buildItem,
- itemCount: list.length,
- onPageChanged: _onPageChanged,
- ),
- bottomSheet: _buildThumb(),
- bottomNavigationBar: _buildBottom(),
- ),
- );
- }
-
- Widget _buildBottom() {
- return Container(
- color: themeColor,
- child: SafeArea(
- child: Container(
- height: 52.0,
- child: Row(
- children: <Widget>[
- Expanded(
- child: Container(),
- ),
- _buildCheckbox(),
- ],
- ),
- ),
- ),
- );
- }
-
- Container _buildCheckbox() {
- return Container(
- constraints: BoxConstraints(
- maxWidth: 150.0,
- ),
- child: StreamBuilder<int>(
- builder: (ctx, snapshot) {
- var index = snapshot.data;
- var data = list[index];
- var checked = selectedList.contains(data);
- return Stack(
- children: <Widget>[
- IgnorePointer(
- child: _buildCheckboxContent(checked, index),
- ),
- Positioned(
- top: 0.0,
- bottom: 0.0,
- left: 0.0,
- right: 0.0,
- child: GestureDetector(
- onTap: () => _changeSelected(!checked, index),
- behavior: HitTestBehavior.translucent,
- child: Container(),
- ),
- ),
- ],
- );
- },
- initialData: widget.initIndex,
- stream: pageStream,
- ),
- );
- }
-
- Widget _buildCheckboxContent(bool checked, int index) {
- return options.checkBoxBuilderDelegate.buildCheckBox(
- context,
- checked,
- index,
- options,
- config.provider,
- );
- }
-
- void _changeSelected(bool isChecked, int index) {
- if (changeProviderOnCheckChange) {
- _onChangeProvider(isChecked, index);
- } else {
- _onCheckInOnlyPreview(isChecked, index);
- }
- }
-
- /// 仅仅修改预览时的状态,在退出时,再更新provider的顺序,这里无论添加与否不修改顺序
- void _onCheckInOnlyPreview(bool check, int index) {
- var item = list[index];
- if (check) {
- selectedList.add(item);
- } else {
- selectedList.remove(item);
- }
- pageChangeController.add(index);
- }
-
- /// 直接修改预览状态,会直接移除item
- void _onChangeProvider(bool check, int index) {
- var item = list[index];
- if (check) {
- selectedProvider.addSelectEntity(item);
- } else {
- selectedProvider.removeSelectEntity(item);
- }
- pageChangeController.add(index);
- }
-
- Widget _buildItem(BuildContext context, int index) {
- var data = list[index];
- return BigPhotoImage(
- assetEntity: data,
- loadingWidget: _buildLoadingWidget(data),
- );
- }
-
- Widget _buildLoadingWidget(AssetEntity entity) {
- return options.loadingDelegate
- .buildBigImageLoading(context, entity, themeColor);
- }
-
- void _onPageChanged(int value) {
- pageChangeController.add(value);
- }
-
- Widget _buildThumb() {
- return StreamBuilder(
- builder: (ctx, snapshot) => Container(
- height: 80.0,
- child: ListView.builder(
- itemBuilder: _buildThumbItem,
- itemCount: previewList.length,
- scrollDirection: Axis.horizontal,
- ),
- ),
- stream: pageStream,
- );
- }
-
- Widget _buildThumbItem(BuildContext context, int index) {
- var item = previewList[index];
- return RepaintBoundary(
- child: GestureDetector(
- onTap: () => changeSelected(item, index),
- child: Container(
- width: 80.0,
- child: Stack(
- children: <Widget>[
- ImageItem(
- themeColor: themeColor,
- entity: item,
- size: options.thumbSize,
- loadingDelegate: options.loadingDelegate,
- ),
- IgnorePointer(
- child: StreamBuilder(
- stream: pageStream,
- builder: (BuildContext context, AsyncSnapshot snapshot) {
- if (selectedList.contains(item)) {
- return Container();
- }
- return Container(
- color: Colors.white.withOpacity(0.5),
- );
- },
- ),
- ),
- ],
- ),
- ),
- ),
- );
- }
-
- void changeSelected(AssetEntity entity, int index) {
- var itemIndex = list.indexOf(entity);
- if (itemIndex != -1) pageController.jumpToPage(itemIndex);
- }
-
- void sure() {
- Navigator.pop(context, selectedList);
- }
- }
-
- class BigPhotoImage extends StatefulWidget {
- final AssetEntity assetEntity;
- final Widget loadingWidget;
-
- const BigPhotoImage({
- Key key,
- this.assetEntity,
- this.loadingWidget,
- }) : super(key: key);
-
- @override
- _BigPhotoImageState createState() => _BigPhotoImageState();
- }
-
- class _BigPhotoImageState extends State<BigPhotoImage>
- with AutomaticKeepAliveClientMixin {
- Widget get loadingWidget {
- return widget.loadingWidget ?? Container();
- }
-
- @override
- Widget build(BuildContext context) {
- super.build(context);
- var width = MediaQuery.of(context).size.width;
- var height = MediaQuery.of(context).size.height;
- return FutureBuilder(
- future:
- widget.assetEntity.thumbDataWithSize(width.floor(), height.floor()),
- builder: (BuildContext context, AsyncSnapshot<Uint8List> snapshot) {
- var file = snapshot.data;
- if (snapshot.connectionState == ConnectionState.done && file != null) {
- print(file.length);
- return Image.memory(
- file,
- fit: BoxFit.contain,
- width: double.infinity,
- height: double.infinity,
- );
- }
- return loadingWidget;
- },
- );
- }
-
- @override
- bool get wantKeepAlive => true;
- }
-
- class PhotoPreviewResult {
- List<AssetEntity> previewSelectedList = [];
- }
|