wechat_assets_picker 2.2.0-dev.2 copy "wechat_assets_picker: ^2.2.0-dev.2" to clipboard
wechat_assets_picker: ^2.2.0-dev.2 copied to clipboard

outdated

An assets picker in pure dart which looks like the one in WeChat, support multi asset pick from device.

example/lib/main.dart

///
/// [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,
            ],
          ),
        ),
      ),
    );
  }
}
752
likes
0
pub points
99%
popularity

Publisher

verified publisherfluttercandies.com

An assets picker in pure dart which looks like the one in WeChat, support multi asset pick from device.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

assets_audio_player, extended_image, flutter, photo_manager, provider, video_player

More

Packages that depend on wechat_assets_picker