Flutter España
Published in

Flutter España

Rotaciones con Transform de Flutter (Part II)- Desafíos

Hola a tod@s!

Después de mi artículo anterior: Rotaciones con Transform de Flutter (Part I)- Ejemplos, ha llegado la hora de publicar la parte II con algunos desafíos.

Recordad que el nivel en estos artículos se puede considerar, de momento, nivel Beginner.

A continuación os mostraré 5 desafíos, como digo, de nivel Beginner.

Si te bloqueas en alguno de ellos, te recomiendo que leas la parte I (el artículo con ejemplos).

¡¡Disfruta mucho y a por ellos!!

El desafío

Clonar este diseño:

No tienes por qué usar el mismo color y el mismo tamaño de letra que aparece en el diseño

Ahora bien, deberías usar únicamente los widgets Container y Transform (mejor el Transform widget envolviendo alContainer widget en vez de la propiedad transform del Container widget)

Y ahora…. ¡ha llegado tu turno! Deja de leer e inténtalo tú mismo sin mirar mi solución. ¡Buena suerte!

Mi solución

Como siempre digo, no es la única solución, tan solo es la mía.

class Challenge extends StatelessWidget {

final Color lightBackground = Color(0xFFB7DEFD);
final Color darkBackground = Color(0xFF62B7FC);
final Color textColor = Color(0xFF04589A);
final double rotationRadians = 0.20;@override
Widget build(BuildContext context) {
return Transform(
transform: Matrix4.rotationZ(rotationRadians),
child: Container(
decoration: BoxDecoration(
color: lightBackground,
borderRadius: BorderRadius.only(
topRight: Radius.circular(40.0),
),
),
alignment: Alignment.center,
child: Transform(
transform: Matrix4.rotationZ(-rotationRadians),
child: Container(
padding: const EdgeInsets.all(25),
decoration: BoxDecoration(
color: darkBackground,
borderRadius: BorderRadius.circular(15.0),
),
child: Text(
'I am a text',
style: TextStyle(
fontSize: 34,
color: textColor,
),
),
),
),
),
);
}
}

Como puedes ver, el Container exterior (azul claro) se envuelve en un Transform para aplicarle la rotación. Este Container contendrá a otro Container (azul oscuro) que también está envuelto en un Transform para poder compensar la rotación que tiene por defecto de su padre y así conseguir que quede horizontal.

El desafío

Partiendo del siguiente diseño:

cuyo código es:

class AirplaneButton extends StatelessWidget {

@override
Widget build(BuildContext context) {

return Container(
decoration: BoxDecoration(
color: Colors.deepPurpleAccent,
shape: BoxShape.circle,
border: Border.all(
color: Colors.deepPurple,
width: 6,
),
),
width: 200,
height: 200,
child: IconButton(
icon: Icon(Icons.airplanemode_active),
iconSize: 95,
color: Colors.white,
onPressed: () {},
),
);
}
}

El desafío consistirá en conseguir el diseño que aparece abajo, reutilizando el AirplaneButton widget:

Reutiliza el AirplaneButton widget y aplica el constructor Transform.rotate para girarlo.

También puedes usar el constructor Transform.translate y/o el Align widget para situarlo donde se necesita.

Y ahora inténtalo tú mismo sin mirar mi solución. ¡Buena Suerte!

Mi solución

Recuerda que no es la única solución, tan solo es la mía.

Transform.translate(
offset: Offset(50, -50),
child: Align(
alignment: Alignment.topRight,
child: Transform.rotate(
angle: -2.2,
alignment: Alignment.center,
child: AirplaneButton(),
),
),
)

El desafío

Dados los siguientes decorations y styles:

final kGreenDecoration = BoxDecoration(
color: Colors.lightGreenAccent,
borderRadius: BorderRadius.circular(10.0),
);
final kBlueDecoration = BoxDecoration(
color: Colors.lightBlueAccent,
borderRadius: BorderRadius.circular(10.0),
);
final kPurpleDecoration = BoxDecoration(
color: Colors.purpleAccent,
borderRadius: BorderRadius.circular(10.0),
);
final kOrangeDecoration = BoxDecoration(
color: Colors.deepOrangeAccent,
borderRadius: BorderRadius.circular(10.0),
);
final kAmberDecoration = BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(10.0),
);
const kTextStyle = TextStyle(
fontSize: 150,
color: Colors.white,
);

Úsalos para conseguir el siguiente diseño:

Fíjate en el origen de las rotaciones ya que éste cambia, no es el mismo origen para todas las rotaciones.

En cuanto al valor de los ángulos de rotación y a los tamaños de los widgets, elige los que veas convenientes para aproximarte a este diseño.

¡Te toca intentarlo a ti! ¡Buena suerte y no mires mi solución antes de intentarlo tú mismo!

Mi solución

¡Ya sabes que esta no es la única solución!

Container(
margin: EdgeInsets.all(80),
decoration: kGreenDecoration,
width: 200,
height: 200,
child: Transform.rotate(
angle: 0.2,
alignment: Alignment.topLeft,
child: Container(
decoration: kBlueDecoration,
child: Transform.rotate(
angle: 0.2,
alignment: Alignment.topLeft,
child: Container(
decoration: kPurpleDecoration,
child: Transform.rotate(
angle: -0.2,
alignment: Alignment.topRight,
child: Container(
decoration: kOrangeDecoration,
child: Transform.rotate(
angle: -0.2,
alignment: Alignment.topRight,
child: Container(
decoration: kAmberDecoration,
alignment: Alignment.center,
child: Transform.rotate(
angle: 0.8,
alignment: Alignment.center,
child: Text(
'A',
style: kTextStyle,
),
),
),
),
),
),
),
),
),
),
)

El desafío

Dado el siguiente texto de “ Star Wars Episode IV - A new hope”:

const String text = 
'It is a period of civil war. Rebel spaceships, ' +
'striking from a hidden base, have won their first victory ' +
'against the evil Galactic Empire. During the battle, ' +
'Rebel spies managed to steal secret plans to the Empire’s ' +
'ultimate weapon...';

Intenta reproducir un diseño similar a:

Este diseño es estático, al igual que el resto de diseños. En futuros artículos, intentaremos darle dinamismo con una animación.

Y ahora… ¡ha llegado tu turno! ¡Buena suerte!

Mi solución

Que por si no lo había mencionado, no es la única solución, es tan solo la mía.

Container(
width: double.infinity,
height: double.infinity,
color: Colors.black,
alignment: Alignment.topCenter,
child: Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.003)
..rotateX(-1.0),
alignment: Alignment.center
child: Container(
width: 250,
height: double.infinity,
color: Colors.black,
alignment: Alignment.center,
child: Text(
text,
style: TextStyle(
fontSize: 28,
color: Colors.yellow,
),
textAlign: TextAlign.justify,
),
),
),
)

Te recomiendo “trastear” con este código, cambiando los valores en negrita y viendo qué ocurre. Te aconsejo cambiar los valores variable a variable y observar el resultado en cada cambio para extraer conclusiones antes de cambiar todas las variables al mismo tiempo.

El desafío

Dados los sieguientes colores:

const colors = [
Color(0xFF2257A3),
Color(0xFF2E22A3),
Color(0xFF6E22A3),
Color(0xFFA32296),
Color(0xFFA32357),
Color(0xFFA32D22)
];

Intenta crear algo parecido a lo siguiente:

¡Suerte! ¡Tú puedes!

Mi solución

Ahora más que nunca, he de decir que la siguiente solución no es la única, tan solo es la mía.

Como verás, he optado por una estrategia de implementación recursiva más que iterativa.

Como parte de esta solución, he creado para este desafío un widget separado para después reutilizarlo pasándole una lista de colores (por ejemplo la lista de colores del enunciado). Al final de estas explicaciones, reutilizaré este widget pasándole la lista y así poder ejecutar la solución.

class MyCustomWidget extends StatelessWidget {

final double circleSize = 90;
final List<Color> colors;
Challenge(this.colors); @override
Widget build(BuildContext context) {
return getWidget(0);
}
Widget getWidget(int index) {

if (index < colors.length) {

double rotationAngle =
(index == 0 || colors.length <= 1) ? 0 :
pi / (colors.length - 1);
return Transform.rotate(
angle: rotationAngle,
origin: Offset(0, 250),
child: Container(
decoration: BoxDecoration(
color: colors[index],
shape: BoxShape.circle,
),
width: circleSize,
height: circleSize,
child: getWidget(index + 1),
),
);

} else
return null;
}
}

250 es el valor a lo largo del eje Y que he elegido para mover el origen por defecto y situarlo donde necesito en cada rotación.

Es decir,

Por ejemplo, usando 150 en vez de 250, conseguimos algo como lo siguiente donde los widgets se juntan más:

Y ahora, se reutilizará el widget programado anteriormente y se le pasará la lista de colores para tener la solución finalmente implementada:

const kColors = [
Color(0xFF2257A3),
Color(0xFF2E22A3),
Color(0xFF6E22A3),
Color(0xFFA32296),
Color(0xFFA32357),
Color(0xFFA32D22)
];
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Challenge'),
),
body: MyCustomWidget(kColors),
),
),
);
}

Y nada más, esto es todo amig@s!

¡¡ Espero que el artículo os haya gustado y os sea muy útil !!

¡Hasta la próxima!

--

--

Actualidad de Flutter en España y Español

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store