diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index bb02592..ee96304 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -11,7 +11,7 @@ import '../extensions/l10n_extensions.dart'; import '../main.dart'; import '../models/picker_method.dart'; import '../widgets/method_list_view.dart'; -import '../widgets/selected_assets_view.dart'; +import '../widgets/selected_assets_list_view.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -22,13 +22,12 @@ class HomePage extends StatefulWidget { class _MyHomePageState extends State { final ValueNotifier isDisplayingDetail = ValueNotifier(true); - final ValueNotifier selectedAsset = - ValueNotifier(null); + List assets = []; Future selectAssets(PickMethod model) async { - final AssetEntity? result = await model.method(context); + final result = await model.method(context); if (result != null) { - selectedAsset.value = result; + assets = [...assets, result]; if (mounted) { setState(() {}); } @@ -110,19 +109,15 @@ class _MyHomePageState extends State { onSelectMethod: selectAssets, ), ), - ValueListenableBuilder( - valueListenable: selectedAsset, - builder: (_, AssetEntity? asset, __) { - if (asset == null) { - return const SizedBox.shrink(); - } - return SelectedAssetView( - asset: asset, - isDisplayingDetail: isDisplayingDetail, - onRemoveAsset: () => selectedAsset.value = null, - ); - }, - ), + if (assets.isNotEmpty) + SelectedAssetsListView( + assets: assets, + isDisplayingDetail: isDisplayingDetail, + onRemoveAsset: (int index) { + assets.removeAt(index); + setState(() {}); + }, + ), ], ), ), diff --git a/example/lib/widgets/selected_assets_list_view.dart b/example/lib/widgets/selected_assets_list_view.dart new file mode 100644 index 0000000..70c2cc1 --- /dev/null +++ b/example/lib/widgets/selected_assets_list_view.dart @@ -0,0 +1,147 @@ +// Copyright 2019 The FlutterCandies author. All rights reserved. +// Use of this source code is governed by an Apache license that can be found +// in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:wechat_camera_picker/wechat_camera_picker.dart'; + +import '../extensions/l10n_extensions.dart'; +import 'asset_widget_builder.dart'; +import 'preview_asset_widget.dart'; + +class SelectedAssetsListView extends StatelessWidget { + const SelectedAssetsListView({ + super.key, + required this.assets, + required this.isDisplayingDetail, + required this.onRemoveAsset, + }); + + final List assets; + final ValueNotifier isDisplayingDetail; + final void Function(int index) onRemoveAsset; + + Widget _selectedAssetWidget(BuildContext context, int index) { + final AssetEntity asset = assets.elementAt(index); + return ValueListenableBuilder( + valueListenable: isDisplayingDetail, + builder: (_, bool value, __) => GestureDetector( + onTap: () async { + if (value) { + showDialog( + context: context, + builder: (BuildContext context) => GestureDetector( + onTap: Navigator.of(context).pop, + child: Center(child: PreviewAssetWidget(asset)), + ), + ); + } + }, + child: RepaintBoundary( + child: ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: AssetWidgetBuilder( + entity: asset, + isDisplayingDetail: value, + ), + ), + ), + ), + ); + } + + Widget _selectedAssetDeleteButton(BuildContext context, int index) { + return GestureDetector( + onTap: () => onRemoveAsset(index), + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4.0), + color: Theme.of(context).canvasColor.withOpacity(0.5), + ), + child: const Icon(Icons.close, size: 18.0), + ), + ); + } + + Widget selectedAssetsListView(BuildContext context) { + return Expanded( + child: ListView.builder( + shrinkWrap: true, + physics: const BouncingScrollPhysics(), + padding: const EdgeInsets.symmetric(horizontal: 8.0), + scrollDirection: Axis.horizontal, + itemCount: assets.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 16.0, + ), + child: AspectRatio( + aspectRatio: 1.0, + child: Stack( + children: [ + Positioned.fill(child: _selectedAssetWidget(context, index)), + ValueListenableBuilder( + valueListenable: isDisplayingDetail, + builder: (_, bool value, __) => AnimatedPositioned( + duration: kThemeAnimationDuration, + top: value ? 6.0 : -30.0, + right: value ? 6.0 : -30.0, + child: _selectedAssetDeleteButton(context, index), + ), + ), + ], + ), + ), + ); + }, + ), + ); + } + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: isDisplayingDetail, + builder: (_, bool value, __) => AnimatedContainer( + duration: kThemeChangeDuration, + curve: Curves.easeInOut, + height: assets.isNotEmpty + ? value + ? 120.0 + : 80.0 + : 40.0, + child: Column( + children: [ + SizedBox( + height: 20.0, + child: GestureDetector( + onTap: () { + if (assets.isNotEmpty) { + isDisplayingDetail.value = !isDisplayingDetail.value; + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(context.l10n.selectedAssetsText), + if (assets.isNotEmpty) + Padding( + padding: const EdgeInsetsDirectional.only(start: 10.0), + child: Icon( + value ? Icons.arrow_downward : Icons.arrow_upward, + size: 18.0, + ), + ), + ], + ), + ), + ), + selectedAssetsListView(context), + ], + ), + ), + ); + } +} diff --git a/example/lib/widgets/selected_assets_view.dart b/example/lib/widgets/selected_assets_view.dart deleted file mode 100644 index f16d4c1..0000000 --- a/example/lib/widgets/selected_assets_view.dart +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2019 The FlutterCandies author. All rights reserved. -// Use of this source code is governed by an Apache license that can be found -// in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:wechat_camera_picker/wechat_camera_picker.dart'; - -import '../extensions/l10n_extensions.dart'; -import 'asset_widget_builder.dart'; -import 'preview_asset_widget.dart'; - -class SelectedAssetView extends StatelessWidget { - const SelectedAssetView({ - super.key, - required this.asset, - required this.isDisplayingDetail, - required this.onRemoveAsset, - }); - - final AssetEntity asset; - final ValueNotifier isDisplayingDetail; - final VoidCallback onRemoveAsset; - - Widget _selectedAssetWidget(BuildContext context) { - return ValueListenableBuilder( - valueListenable: isDisplayingDetail, - builder: (_, bool value, __) => GestureDetector( - onTap: () async { - if (value) { - showDialog( - context: context, - builder: (BuildContext context) => GestureDetector( - onTap: Navigator.of(context).pop, - child: Center(child: PreviewAssetWidget(asset)), - ), - ); - } - }, - child: RepaintBoundary( - child: ClipRRect( - borderRadius: BorderRadius.circular(8), - child: AssetWidgetBuilder(entity: asset, isDisplayingDetail: value), - ), - ), - ), - ); - } - - Widget _selectedAssetDeleteButton(BuildContext context) { - return GestureDetector( - onTap: onRemoveAsset, - child: DecoratedBox( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: Theme.of(context).canvasColor.withOpacity(0.5), - ), - child: const Icon(Icons.close, size: 18), - ), - ); - } - - Widget _selectedAssetView(BuildContext context) { - return Container( - alignment: Alignment.center, - padding: const EdgeInsets.all(16), - child: AspectRatio( - aspectRatio: 1, - child: Stack( - children: [ - Positioned.fill(child: _selectedAssetWidget(context)), - ValueListenableBuilder( - valueListenable: isDisplayingDetail, - builder: (_, bool value, Widget? child) => AnimatedPositioned( - duration: kThemeAnimationDuration, - top: value ? 6 : -30, - right: value ? 6 : -30, - child: child!, - ), - child: _selectedAssetDeleteButton(context), - ), - ], - ), - ), - ); - } - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: isDisplayingDetail, - builder: (_, bool value, Widget? child) => AnimatedContainer( - duration: kThemeChangeDuration, - curve: Curves.easeInOut, - height: value ? 120 : 80, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: 20, - child: GestureDetector( - onTap: () => - isDisplayingDetail.value = !isDisplayingDetail.value, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text(context.l10n.selectedAssetsText), - Padding( - padding: const EdgeInsetsDirectional.only(start: 10), - child: Icon( - value ? Icons.arrow_downward : Icons.arrow_upward, - size: 18, - ), - ), - ], - ), - ), - ), - Expanded(child: child!), - ], - ), - ), - child: _selectedAssetView(context), - ); - } -}