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(
colorScheme: .fromSeed(seedColor: Colors.deepPurple),
),
showPerformanceOverlay: true, // Enables the performance overlay
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const double _minRadius = 1;
static const double _maxRadius = 500;
static const double _defaultRadius = 150;
double _turns = 0;
double _radius = _defaultRadius;
final _controller = TextEditingController(text: '$_defaultRadius');
void _turn() {
setState(() {
_turns += 5;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: .center,
children: [
AnimatedRotation(
turns: _turns,
duration: Duration(seconds: 10),
child: CustomPaint(
foregroundPainter: _MyCirclePainter(rows: 50, cols: 50, radius: _radius),
size: Size(400, 400),
),
)
],
),
),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: .center,
children: <Widget>[
ElevatedButton(onPressed: _turn, child: Text('Turn')),
SizedBox(width: 20),
Text('Radius'),
Slider(
value: _radius,
min: _minRadius,
max: _maxRadius,
onChanged: (value) {
setState(() {
_radius = value;
_controller.text = _radius.toStringAsFixed(1);
});
},
),
SizedBox(
width: 100,
child: TextField(
controller: _controller,
keyboardType: .number,
onSubmitted: (newString) {
double? newValue = double.tryParse(newString);
if (newValue != null) {
setState(() {
_radius = newValue.clamp(_minRadius, _maxRadius);
});
}
},
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(),
),
),
),
],
),
),
);
}
}
class _MyCirclePainter extends CustomPainter {
static final List<Color> colors = <Color>[
Colors.purple,
Colors.blue,
Colors.green,
Colors.yellow,
Colors.orange,
Colors.red,
];
_MyCirclePainter({required this.rows, required this.cols, required this.radius});
final int rows;
final int cols;
final double radius;
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.fill;
paint.color = Colors.white;
canvas.drawRect(Offset.zero & size, paint);
Size gridSize = Size(2 * radius * cols, 2 * radius * rows);
Size gridSpace = Size(
size.width - gridSize.width,
size.height - gridSize.height,
);
Size cellPadding = Size(
gridSpace.width / (cols + 1),
gridSpace.height / (rows + 1),
);
canvas.translate(cellPadding.width + radius, cellPadding.height + radius);
int colorIndex = 0;
for (int y = 0; y < rows; y++) {
double circleY = (cellPadding.height + radius * 2) * y;
for (int x = 0; x < cols; x++) {
double circleX = (cellPadding.width + radius * 2) * x;
paint.color = colors[colorIndex++ % colors.length];
canvas.drawCircle(Offset(circleX, circleY), radius, paint);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
Steps to reproduce
Compile and run the following example. The results I describe below are from running this app on my Macbook Pro with M1 Max. The slider and textfield allow you to adjust the radius. Clicking the "Turn" button will initiate a 5 full 360 degree turn animation that demonstrates if the rendering is smooth at that radius size.
On Skia:
On Impeller:
Expected results
Normal rendering at a radius of 100:
Impeller results at radius == 100
Actual results
Corrupted rendering:
Corrupted Impeller rendering at radius == 150
the results are more dramatic if you move the mouse over the bottom app bar while it is animating and increase the radius.
Code sample
Code sample
Screenshots or Video
No response
Logs
The following errors were noted on the console from which the app was launched.
Logs
Flutter Doctor output
Doctor output