-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Steps to reproduce
- Create a
CustomPainterand make a path that draws an arc. Draw this path onto the canvas using thedrawPath()method oncanvas. - Make a variable called
startAngleand put it in the constructor so that we can modify the rotation of the painter to see the artifacts. - Wrap the
canvas.drawPath()method withsaveLayer()andrestore()functions which basically create a new stack onto the canvas. - Use this custom painter in a
CustomPaintwidget and wrap it with an animation widget like theAnimatedBuilderand supply an animation to see the artifacts across multiple frames.
Note: drawing an arc using the drawArc() method of the canvas will not produce this error. And drawing a circle with the drawOval() method on path will also not produce the error. The arc has to be made with a Path using the drawArc() method.
Expected results
The flickering should not happen at the left and top portions of the painter when we use saveLayer() and restore(). When we do not use these functions, we do not get the flickering issue.
Actual results
We do see some flickering which most likely happens for some values of startAngle. Because when we pause the animation at random, we get a still frame with the artifact.
I don't have an iPhone to test on a real device but I can confirm this behaviour with impeller enabled on iOS and Android emulators along with physical Android device. On disabling impeller, we do not see these issues at all.
Code sample
Code sample
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorSchemeSeed: Colors.deepPurple,
useMaterial3: true,
),
home: const MyWidget(),
);
}
}
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
late AnimationController controller;
@override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: const Duration(seconds: 5))
..repeat(reverse: true);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedBuilder(
animation: controller,
builder: (context, _) {
return CustomPaint(
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.width),
painter: MyPaint(startAngle: pi / 2 * controller.value),
);
}),
),
),
);
}
}
class MyPaint extends CustomPainter {
final double startAngle;
MyPaint({
required this.startAngle,
});
@override
void paint(Canvas canvas, Size size) {
final width = size.width;
final height = size.height;
final center = Offset(width / 2, height / 2);
final paint = Paint()
..color = Colors.orangeAccent
..style = PaintingStyle.fill;
final path = Path()
..addArc(Rect.fromCenter(center: center, width: width, height: height),
startAngle, 1.99 * pi);
canvas.saveLayer(
Rect.fromCenter(center: center, width: width, height: height),
Paint(),
);
canvas.drawPath(path, paint);
canvas.restore();
}
@override
bool shouldRepaint(MyPaint oldDelegate) =>
oldDelegate.startAngle != startAngle;
}
Screenshots or Video
Screenshots / Video demonstration
Simulator.Screen.Recording.-.iPhone.14.Pro.Max.-.2023-06-09.at.01.23.36.mp4
Logs
Logs
No logs produced
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.10.4, on macOS 13.4 22F66 darwin-arm64, locale en-IN)
• Flutter version 3.10.4 on channel stable at /Users/ashishbeck/Dev/Tools/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 682aa387cf (3 days ago), 2023-06-05 18:04:56 -0500
• Engine revision 2a3401c9bb
• Dart version 3.0.3
• DevTools version 2.23.1
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
• Android SDK at /Users/ashishbeck/Library/Android/sdk
• Platform android-33, build-tools 33.0.0
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 14E300c
• CocoaPods version 1.12.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2021.2)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
[✓] VS Code (version 1.78.2)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.64.0
[✓] Connected device (3 available)
• iPhone 14 Pro Max (mobile) • CB613DEA-6EC4-46AC-A1C1-8E2C893480CB • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-4
(simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 13.4 22F66 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 114.0.5735.106
[✓] Network resources
• All expected network resources are available.
• No issues found!