flutter中的RiverPod可以存储图像吗?

问题描述 投票:0回答:1

我在 flutter 中使用 Riverpod 进行状态管理。我需要让用户选择一个图像,裁剪它,在将其上传到服务器之前暂时存储它。因此,我正在考虑将图像存储在 Riverpod 提供程序中,该提供程序保存也应该上传的其他数据。 Riverpod可以存储这样的图像吗?这是一个好方法吗?如果没有,为什么?更好的方法是什么?

flutter riverpod
1个回答
0
投票

可以参考这个代码

import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import 'buttons.dart';

part 'image_cropper.g.dart';

/// Provider to temporarily hold cropped image.
@riverpod
class CroppedImage extends _$CroppedImage {
  @override
  XFile? build() {
    return null;
  }
}

/// Crop image.
Future<XFile> cropImage(
  BuildContext context,
  XFile imageFile,
) async {
  final croppedFile = await ImageCropper().cropImage(
    sourcePath: imageFile.path,
    aspectRatio: const CropAspectRatio(
      ratioX: 1,
      ratioY: 2,
    ),
    uiSettings: [
      // Android setting.
      AndroidUiSettings(
        toolbarColor: Colors.black,
        toolbarWidgetColor: Colors.white,
        initAspectRatio: CropAspectRatioPreset.ratio5x4,
        lockAspectRatio: true,
        hideBottomControls: true,
      ),
      // iOS setting.
      IOSUiSettings(
        minimumAspectRatio: 1,
        rotateButtonsHidden: true,
        aspectRatioPickerButtonHidden: true,
      ),
      // Web settings.
      WebUiSettings(
        context: context,
        presentStyle: CropperPresentStyle.page,
        barrierColor: AppColors.blackOverlayColor,
        showZoomer: true,
        enableZoom: true,
        boundary: CroppieBoundary(
          width: context.screenAppWidth.toInt(),
          height: context.screenAppWidth * 5 ~/ 4,
        ),
        viewPort: CroppieViewPort(
          width: (context.screenAppWidth * .9).toInt(),
          height: context.screenAppWidth * .9 * 5 ~/ 4,
        ),
        customRouteBuilder: (cropper, crop, _) {
          return MaterialPageRoute(
            builder: (context) {
              return CropperPage(
                cropper: cropper,
                crop: crop,
                cropperContainerWidth: context.screenAppWidth,
                cropperContainerHeight:
                    (context.screenAppWidth * 5 ~/ 4).toDouble(),
              );
            },
          );
        },
      ),
    ],
  );
  if (croppedFile == null) {
    throw ImagePickerException.failedCrop();
  }

  return XFile(croppedFile.path);
}

class CropperPage extends StatelessWidget {
  const CropperPage({
    super.key,
    required this.cropper,
    required this.crop,
    required this.cropperContainerWidth,
    required this.cropperContainerHeight,
  });

  final Widget cropper;
  final Future<String?> Function() crop;
  final double cropperContainerWidth;
  final double cropperContainerHeight;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          CommonTextButton(
            text: '提出する',
            onPressed: () async {
              final result = await crop();
              if (context.mounted) {
                Navigator.of(context).pop(result);
              }
            },
          ),
        ],
      ),
      body: Column(
        children: [
          const Gap(16),
          const Text('※画像のトリミングに失敗する場合は縦横比率を調整ください。', style: TextStyle(fontSize: 12),),
          const Gap(16),
          Center(
            child: SizedBox(
              width: cropperContainerWidth,
              height: cropperContainerHeight,
              child: cropper,
            ),
          ),
        ],
      ),
    );
  }
}

用途:

final croppedImage = await cropImage(context, image);
© www.soinside.com 2019 - 2024. All rights reserved.