Whether I draw the figure on a canvas with a small or a large scale—by replacing v = 100000.0
with v = 1000.0
in the following code, the image doesn't change, as expected.
(If you are not familiar with the idea of using a SizedBox
inside a FittedBox
, it is explained here.)
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
const v = 10000.0;
class Painter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final mypaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 0.012 * v
..color = Colors.blue;
canvas.drawCircle(
Offset(1.5 * v, 1 * v),
1 * v, mypaint);
}
@override
bool shouldRepaint(Painter oldDelegate) => false;
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "My App",
home: FittedBox(
child: SizedBox(
width: 3 * v,
height: 2 * v,
child: CustomPaint(
painter: Painter()
),
),
),
);
}
}
But if I put MaterialApp
inside a Scaffold
, I still get the image on the left for v = 10000.0
, but with v = 100.0
, I get instead the image on the right.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
const v = 10000.0;
class Painter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final mypaint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 0.012 * v
..color = Colors.blue;
canvas.drawCircle(
Offset(1.5 * v, 1 * v),
1 * v, mypaint);
}
@override
bool shouldRepaint(Painter oldDelegate) => false;
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "My App",
home: Scaffold(
appBar: AppBar(
title: const Text('My Title'),
),
body: FittedBox(
child: SizedBox(
width: 3 * v,
height: 2 * v,
child: CustomPaint(
painter: Painter()
),
),
),
),
);
}
}
How do I get a scale invariant CustomPaint
with a Scaffold
?
As explained in my answer here (saw your comment btw) since FittedBox
does not have minimum constrains passed by Scaffold it will shrink as much as possible being the size of the SizedBox
the smallest it can get thus changing with v
. The solution to this is as simple as passing new constraints telling your FittedBox
to expand as much as possible.
Scaffold(
appBar: AppBar(
title: const Text('My Title'),
),
body: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: double.infinity,
minHeight: double.infinity,
),
child: FittedBox(
child: SizedBox(
width: 3 * v,
height: 2 * v,
child: CustomPaint(painter: Painter()),
),
),
),
),