flutter 有个组件叫做 image_cropper ,近期这个组件也进行了鸿蒙化操作,只不过再使用的时候,我们需要基于这个插件 imagecropper_ohos 进行鸿蒙裁剪图片组件的封装。还是老样子,我们借助官方文档和示例代码来研究怎么使用。插件网址如下:

GitCode - 全球开发者的开源社区,开源代码托管平台GitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode.com/openharmony-sig/fluttertpc_image_cropper/tree/br_v8.0.2_ohos/image_cropper首先,我们将这个仓库下载到本地。

解压后,我们找到这个路径下的文件:

使用VS code打开,并且使用flutter pub get 下载依赖:

接着,我们执行 flutter run,一会后报错提示ohos工程要签名,我们在Dev Eco中进行自动签名:

重新执行flutter run,一会后应用运行在手机上

但此时,应用白屏,遇到问题不慌,咱们解决问题吧:
创建一个新的flutter鸿蒙项目,项目名和之前的项目保持一直,便于依赖的导入:

将之前项目中的lib文件夹复制粘贴到新项目中,并且将依赖文件中的代码复制粘贴过去:

值得注意的是,如果你创建的新项目和老项目的路径不一样,那么这个依赖的path路径要根据新项目和ohos这个依赖的实际的位置进行修改:

然后,我们执行flutter pub get、flutter run、去dev eco给ohos签名、flutter run。一番等待后,成功运行应用:

那么,我们来简化代码,将其封装成一个裁剪图片的工具组件吧:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker_ohos/file_picker_ohos.dart';
import 'dart:async';
import 'package:imagecropper_ohos/imagecropper_ohos.dart';
import 'package:image_picker/image_picker.dart';
import 'package:imagecropper_ohos/page/crop.dart';

Future<void> uploadImage( BuildContext? context) async {
    FilePickerResult? result = await FilePicker.platform.pickFiles(type:FileType.image);
    if (result != null) {
      File pickedFile = File(result.files.single.path!);
          cropImage(pickedFile ,context);
          print("选择的图片路径是:$pickedFile");
    }
  }

Future<void> cropImage( File? pickedFile, BuildContext ?context ) async {
    if (pickedFile != null) {
      String? croppedFile = await Navigator.push<String?>(
        context!,
        MaterialPageRoute(
            builder: (context) => CropWidget(filePath: pickedFile.path,)),
      );
    print("裁剪后的图片路径是:$croppedFile");
    }
  }



class CropWidget extends StatefulWidget {
  final String filePath;

  CropWidget({Key? key, required this.filePath}) : super(key: key);

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<CropWidget> {
  final imageCropper = ImagecropperOhos();
  final cropKey = GlobalKey<CropState>();
  File? _file;
  File? _sample;
  File? _lastCropped;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      imageCropper.sampleImage(
        path: widget.filePath,
        maximumSize: context.size!.longestSide.ceil(),
      ).then((value) {
        setState(() {
          _sample = value!;
          _file = File(widget.filePath);
        });
      });
    });
  }


  @override
  void dispose() {
    super.dispose();
    _sample?.delete();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Container(
          color: Colors.black,
          child: _sample == null ? _buildOpeningImage() : _buildCroppingImage(),
        ),
      ),
    );
  }

  Widget _buildOpeningImage() {
    return Center(child: _buildOpenImage());
  }

  Widget _buildCroppingImage() {
    return Column(
      children: <Widget>[
        Expanded(
          child: Crop.file(_sample!, key: cropKey,),
        ),
        Container(
          padding: const EdgeInsets.only(top: 20.0),
          alignment: AlignmentDirectional.center,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              TextButton(
                child: Text(
                  '确认',
                  style: Theme
                      .of(context)
                      .textTheme
                      .labelLarge
                      ?.copyWith(color: Colors.white),
                ),
                onPressed: () => _cropImage(),
              ),
            ],
          ),
        )
      ],
    );
  }


  Widget _buildOpenImage() {
    return TextButton(
      child: Text(
        'Open Image',
        style: Theme
            .of(context)
            .textTheme
            .labelLarge
            ?.copyWith(color: Colors.white),
      ),
      onPressed: () => _openImage(),
    );
  }

  Future<void> _openImage() async {
    try {
      final pickedFile = await ImagePicker().pickImage(
          source: ImageSource.gallery);
      if (pickedFile == null) return;
      final file = File(pickedFile.path);
      debugPrint('$file');
      final sample = await imageCropper.sampleImage(
        path: pickedFile.path,
        maximumSize: context.size!.longestSide.ceil(),
      );

      _sample?.delete();
      _file?.delete();

      setState(() {
        _sample = sample;
        _file = file;
      });
    } catch (e, s) {
      print(' _openImage $e,$s');
    }
  }

  Future<void> _cropImage() async {
    final scale = cropKey.currentState?.scale;
    final area = cropKey.currentState?.area;
    final angle = cropKey.currentState?.angle;
    final cx = cropKey.currentState?.cx ?? 0;
    final cy = cropKey.currentState?.cy ?? 0;
    if (area == null) {
      // cannot crop, widget is not setup
      return;
    }

    // scale up to use maximum possible number of pixels
    // this will sample image in higher resolution to make cropped image larger
    final sample = await imageCropper.sampleImage(
      path: _file!.path,
      maximumSize: (2000 / scale!).round(),
    );

    final file = await imageCropper.cropImage(
      file: sample!,
      area: area,
      angle: angle,
      cx: cx,
      cy: cy,
    );
    sample.delete();

    _lastCropped?.delete();
    _lastCropped = file;

    Navigator.pop(context, file.path);
  }
}

以上是个人经验分享。

Logo

加入「COC·上海城市开发者社区」,成就更好的自己!

更多推荐