You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter图片裁剪旋转功能实现及组件优化需求

满足需求的EditImage组件修改实现

以下代码实现了你需要的所有功能:显示选中的图片、底部预览小方块切换图片、直接在页面提供裁剪/旋转操作,同时移除了原有的编辑按钮。

class EditImage extends Stateful Widget {
  final List<String> imagePath;

  const EditImage({Key? key, required this.imagePath}) : super(key: key);

  @override
  _EditImageState createState() => _EditImageState();
}

class _EditImageState extends State<EditImage> {
  int currIndex = 0;
  final ImageCropper _imageCropper = ImageCropper();
  late List<String> _listImagePath; // 内部可变列表,用于更新图片路径

  @override
  void initState() {
    super.initState();
    // 将传入的不可变列表转为内部可变列表
    _listImagePath = List.from(widget.imagePath);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.black,
        title: const Text('图片编辑'),
      ),
      body: _listImagePath.isEmpty
          ? const Center(child: Text('没有可编辑的图片'))
          : SingleChildScrollView(
              padding: const EdgeInsets.all(16),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // 显示当前选中的图片
                  Container(
                    width: double.infinity,
                    height: MediaQuery.of(context).size.height * 0.5,
                    decoration: BoxDecoration(
                      border: Border.all(color: Colors.grey),
                    ),
                    child: Image.file(
                      File(_listImagePath[currIndex]),
                      fit: BoxFit.contain,
                    ),
                  ),
                  const SizedBox(height: 20),
                  // 裁剪和旋转操作按钮
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton.icon(
                        onPressed: _cropAndRotateImage,
                        icon: const Icon(Icons.crop),
                        label: const Text('裁剪/旋转'),
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.blue,
                          foregroundColor: Colors.white,
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 30),
                  // 底部图片预览小方块
                  const Text('已选图片预览'),
                  const SizedBox(height: 10),
                  SizedBox(
                    height: 80,
                    child: ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemCount: _listImagePath.length,
                      itemBuilder: (context, index) {
                        return GestureDetector(
                          onTap: () {
                            setState(() {
                              currIndex = index;
                            });
                          },
                          child: Container(
                            margin: const EdgeInsets.symmetric(horizontal: 8),
                            width: 80,
                            height: 80,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: currIndex == index
                                    ? Colors.blue
                                    : Colors.grey,
                                width: 2,
                              ),
                              borderRadius: BorderRadius.circular(8),
                            ),
                            child: ClipRRect(
                              borderRadius: BorderRadius.circular(6),
                              child: Image.file(
                                File(_listImagePath[index]),
                                fit: BoxFit.cover,
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
    );
  }

  Future<void> _cropAndRotateImage() async {
    String imageFilePath = _listImagePath[currIndex];

    try {
      final croppedFile = await _imageCropper.cropImage(
        sourcePath: imageFilePath,
        aspectRatioPresets: [
          CropAspectRatioPreset.square,
          CropAspectRatioPreset.ratio3x2,
          CropAspectRatioPreset.original,
          CropAspectRatioPreset.ratio4x3,
          CropAspectRatioPreset.ratio16x9,
        ],
        compressQuality: 100,
        // 启用旋转功能,Android和iOS的UI设置中默认支持旋转操作
        uiSettings: [
          AndroidUiSettings(
            toolbarTitle: '图片编辑',
            toolbarColor: Colors.blue,
            toolbarWidgetColor: Colors.white,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false,
            showCropGrid: true,
          ),
          // 如需支持iOS,取消下面注释
          // IOSUiSettings(
          //   title: '图片编辑',
          //   rotateButtonsHidden: false,
          // ),
        ],
      );

      if (croppedFile != null) {
        setState(() {
          _listImagePath[currIndex] = croppedFile.path;
        });
      }
    } catch (e) {
      print("编辑图片出错: $e");
    }
  }
}

关键修改说明

  • 内部可变列表:由于传入的imagePath是不可变的final列表,在initState中转为内部的_listImagePath,方便裁剪后更新图片路径。
  • 底部预览小方块:用横向ListView实现,点击任意小方块可切换当前显示的图片,选中的图片会有蓝色边框标记。
  • 直接显示操作按钮:移除原编辑按钮,直接在主图片下方放置裁剪/旋转按钮,点击后打开的裁剪器内置旋转功能,可在编辑界面直接操作旋转。
  • 图片显示优化:给主图片容器添加边框并设置固定高度,保证不同设备上的显示一致性。

内容的提问来源于stack exchange,提问作者Hafsa Azram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 14:37:27