I want to learn more about offset, I googled and found very few tutorials.
I found this tutorial https://blog.logrocket.com/understanding-offsets-flutter/ but is a bit complex.
I learned somewhere that it was expressed from the center of the screen Offset(0,0) (with Offset(dx,dy) and for instance:
- Offset(1,0) was the center right
- Offset(-1,0) was the center left
- Offset(0,1) was the bottom center
- Offset(0,-1) was the top center
but I have other examples with Offset(30,20) …
I am lost, in which unit is it expressed?
Does in depend on the type of widget?
Is there a simple tutorial out there?
Thank you!
Offset
, Alignment
, Rect
, and Size
are all very important to understand. I spend a bit of time reviewing their protocols from time to time, and it pays off when I must deal with Positioned
widgets inside a Stack
, or painting on the canvas with CustomPainter
.
It scares me to see all these painting apps that deal with x and y as pairs of variables, instead of using the self-paired offsets and math on those. Especially cool is Offset.fromDirection
which does a polar-to-rect calculation, meaning you don’t have to remember your trig very much to lay out that clock-face.
What an Offset
does depends entirely on the Widget
it’s used in. See this full example:
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(
home: OffSetTest(),
));
class OffSetTest extends StatelessWidget {
const OffSetTest({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
OffSetBox(dx: 0, dy: 0, color: Colors.red),
OffSetBox(dx: 1, dy: 1, color: Colors.green),
OffSetBox(dx: 2, dy: 2, color: Colors.blue),
OffSetBox(dx: 3, dy: 3, color: Colors.yellow),
OffSetBox(dx: 4, dy: 4, color: Colors.purple),
],
),
),
);
}
}
class OffSetBox extends StatelessWidget {
final double dx;
final double dy;
final Color color;
const OffSetBox(
{super.key, required this.dx, required this.dy, required this.color});
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(dx, dy),
child: Container(
width: 100,
height: 100,
color: color,
child: Text('$dx, $dy'),
),
);
}
}
Here we use it in an Transform.translate
and there the values used in the Offset
equal the number of pixels it will be shifted, so you get this output:
If we replace it with an FractionalTranslation
instead like this:
class OffSetBox extends StatelessWidget {
final double dx;
final double dy;
final Color color;
const OffSetBox(
{super.key, required this.dx, required this.dy, required this.color});
@override
Widget build(BuildContext context) {
return FractionalTranslation(
translation: Offset(dx, dy),
child: Container(
width: 100,
height: 100,
color: color,
child: Text('$dx, $dy'),
),
);
}
}
we get this instead while using the same offsets:
Here it shifts according to its own size.
And there’s also FractionalOffset
s for example. For example:
class OffSetBox extends StatelessWidget {
final double dx;
final double dy;
final Color color;
const OffSetBox(
{super.key, required this.dx, required this.dy, required this.color});
@override
Widget build(BuildContext context) {
return Align(
alignment: FractionalOffset(dx, dy),
child: Container(
width: 500,
height: 500,
color: color,
child: Text('$dx, $dy'),
),
);
}
}
Here 0,0 corresponds to the topleft of the parent. 1,1 to bottomleft. And 2,2 will then mean the position so 1,1 is exactly in between etc. So behavior also depends on the the window size.
There’s many more possibilities where in each it could mean something else
“in which unit is it expressed?” – Offset’s
dx
anddy
are expressed as “logical” pixels, the same values you use in Container’swidth
andheight
properties