-
Notifications
You must be signed in to change notification settings - Fork 132
Open
Description
Version
1.0.0
Platforms
dart
Device Model
iPhone 16 Pro
flutter info
[✓] Flutter (Channel stable, 3.27.4, on macOS 15.3.2 24D81 darwin-arm64, locale zh-Hans-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/to/macos-android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2025.1.2)
[✓] VS Code (version 1.100.3)
[!] Proxy Configuration
! NO_PROXY is not set
[✓] Connected device (7 available)
[✓] Network resources
! Doctor found issues in 2 categories.How to reproduce?
- Navigate to image crop page through GoRouter with a local image path parameter
- Load image using
ExtendedImage.filewithExtendedImageMode.editor - Set custom
CircleEditorCropLayerPainterascropLayerPainter - Page loads and triggers assertion error
Logs
════════ Exception caught by scheduler library ═════════════════════════════════
The following assertion was thrown during a scheduler callback:
'package:flutter/src/rendering/object.dart': Failed assertion: line 1191 pos 20: 'node.isRepaintBoundary': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=2_bug.yml
When the exception was thrown, this was the stack:
#2 PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1191:20)
object.dart:1191
#3 PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1203:15)
object.dart:1203
#4 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:611:23)
binding.dart:611
#5 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1178:13)
binding.dart:1178
#6 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:475:5)
binding.dart:475
#7 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1397:15)
binding.dart:1397
#8 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1318:9)
binding.dart:1318
#9 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1176:5)
binding.dart:1176
#10 _invoke (dart:ui/hooks.dart:312:13)
hooks.dart:312
#11 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:427:5)
platform_dispatcher.dart:427
#12 _drawFrame (dart:ui/hooks.dart:283:31)
hooks.dart:283
(elided 2 frames from class _AssertionError)Example code (optional)
import 'dart:io';
import 'dart:typed_data';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_editor/image_editor.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
class ImageCropPage extends StatefulWidget {
const ImageCropPage({super.key, required this.imagePath});
final String imagePath;
@override
State<ImageCropPage> createState() => _ImageCropPageState();
}
final GlobalKey<ExtendedImageEditorState> editorKey =
GlobalKey<ExtendedImageEditorState>();
class _ImageCropPageState extends State<ImageCropPage> {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: NavigationBarView(
title: t.utility.cropImage,
trailing: PureButton(
padding: EdgeInsets.only(right: 15.w),
onPressed: _cropImage,
child: Assets.setting.cropConfirm.image(width: 36.w, height: 36.w),
),
),
child: ExtendedImage.file(
File(widget.imagePath),
fit: BoxFit.contain,
mode: ExtendedImageMode.editor,
enableLoadState: true,
cacheRawData: true,
extendedImageEditorKey: editorKey,
initEditorConfigHandler: (state) {
return EditorConfig(
maxScale: 6.0,
cropRectPadding: const EdgeInsets.all(20.0),
hitTestSize: 20.0,
cropAspectRatio: CropAspectRatios.ratio1_1,
cropLayerPainter: const CircleEditorCropLayerPainter(),
);
},
),
);
}
}
class CircleEditorCropLayerPainter extends EditorCropLayerPainter {
const CircleEditorCropLayerPainter();
@override
void paint(
Canvas canvas,
Size size,
ExtendedImageCropLayerPainter painter,
Rect rect,
) {
final Rect cropRect = painter.cropRect;
final Paint paint = Paint()..color = painter.maskColor;
final Path mask = Path()
..addOval(cropRect)
..addRect(Rect.fromLTWH(0, 0, size.width, size.height))
..fillType = PathFillType.evenOdd;
canvas.saveLayer(Rect.fromLTWH(0, 0, size.width, size.height), Paint());
canvas.drawPath(mask, paint);
canvas.restore();
final Paint borderPaint = Paint()
..color = Colors.white
..style = PaintingStyle.stroke
..strokeWidth = 2.0;
canvas.drawOval(cropRect, borderPaint);
}
}Contact
No response
Metadata
Metadata
Assignees
Labels
No labels