Flutter (32): Transform

Time: Column:Mobile & Frontend views:201

Transform

Transform can apply matrix transformations to its child component when rendering, allowing for various visual effects. Matrix4 is a 4D matrix through which we can perform different matrix operations. Below is an example:

Container(
  color: Colors.black,
  child: Transform(
    alignment: Alignment.topRight, // Alignment relative to the origin of the coordinate system
    transform: Matrix4.skewY(0.3), // Skew 0.3 radians along the Y-axis
    child: Container(
      padding: const EdgeInsets.all(8.0),
      color: Colors.deepOrange,
      child: const Text('Apartment for rent!'),
    ),
  ),
)

The result is shown in Figure:

Flutter (32): Transform

Matrix transformations involve linear algebra, which is outside the scope of this book. Readers interested in matrix math can explore this topic independently. In this book, we’ll focus on common transformation effects in Flutter. Additionally, since matrix transformations occur during the rendering phase without triggering layout or rebuild processes, performance is generally very good.

32.1 Translation

Transform.translate takes an offset parameter that allows you to move the child component along the x and y axes by a specified distance during rendering.

DecoratedBox(
  decoration: BoxDecoration(color: Colors.red),
  // The default origin is the top-left corner. Move 20 pixels left and 5 pixels up.
  child: Transform.translate(
    offset: Offset(-20.0, -5.0),
    child: Text("Hello world"),
  ),
)

The result is shown in Figure :

Flutter (32): Transform

32.2 Rotation

Transform.rotate can rotate a child component, for example:

DecoratedBox(
  decoration: BoxDecoration(color: Colors.red),
  child: Transform.rotate(
    // Rotate 90 degrees
    angle: math.pi / 2,
    child: Text("Hello world"),
  ),
)

Note: To use math.pi, you need to import the following package:

import 'dart:math' as math;

The result is shown in Figure :

Flutter (32): Transform

32.3 Scaling

Transform.scale can scale a child component up or down, as in this example:

DecoratedBox(
  decoration: BoxDecoration(color: Colors.red),
  child: Transform.scale(
    scale: 1.5, // Scale to 1.5 times the size
    child: Text("Hello world"),
  ),
);

The result is shown in Figure :

Flutter (32): Transform

32.4 Notes on Transform

Transformations applied via Transform occur during the rendering phase, not the layout phase. This means that no matter what transformations are applied to the child, the size and position on the screen remain fixed, as these are determined during the layout phase. Let’s explain this in detail:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      child: Transform.scale(scale: 1.5, 
          child: Text("Hello world")),
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0)),
  ],
)

The result is shown in Figure :

Flutter (32): Transform

After applying a transformation (scaling) to the first Text, the text is scaled up during rendering, but the occupied space remains the same (the red area), so the second Text is rendered right next to the red area, resulting in text overlap.

Since matrix transformations only affect the rendering phase, they can be used to create visual changes in the UI without triggering the build process, saving on layout costs and improving performance. For example, the Flow widget internally uses matrix transformations to update the UI, and many Flutter animation components also use Transform extensively to enhance performance.

Thought Experiment: If you apply a translation and then a rotation (or vice versa) to a child component using Transform, will the final effect be the same? Why?

32.5 RotatedBox

RotatedBox is similar to Transform.rotate in that both can rotate a child component, but there is a key difference: RotatedBox applies the transformation during the layout phase, which affects the position and size of the child. Let’s modify the previous Transform.rotate example:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      // Replace Transform.rotate with RotatedBox
      child: RotatedBox(
        quarterTurns: 1, // Rotate 90 degrees (1/4 turn)
        child: Text("Hello world"),
      ),
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0)),
  ],
)

The result is shown in Figure :

Flutter (32): Transform

Since RotatedBox operates during the layout phase, the child component is rotated 90 degrees (not just its rendered content). The decoration will apply to the actual space occupied by the child component, resulting in the layout shown above. Compare this with the previous Transform.rotate example for a better understanding.