Skip to content

Instantly share code, notes, and snippets.

@codesxt
Created October 4, 2023 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codesxt/33cb79bdedcf15b39231d9d89d8c8be8 to your computer and use it in GitHub Desktop.
Save codesxt/33cb79bdedcf15b39231d9d89d8c8be8 to your computer and use it in GitHub Desktop.
Flutter Themes and State Example
import 'package:flutter/material.dart';
import 'dart:async';
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: ColorScheme.fromSeed(
seedColor: Colors.deepOrange,
),
textTheme: const TextTheme(
displayLarge: TextStyle(),
),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepOrange,
brightness: Brightness.dark,
),
textTheme: const TextTheme(
displayLarge: TextStyle(),
),
useMaterial3: true,
brightness: Brightness.dark,
),
themeMode: ThemeMode.dark,
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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Theme(
data: ThemeData(
brightness: Brightness.light,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CardCount(
text: 'El valor de la variable es',
count: _counter,
),
const TimerCard(),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class CardCount extends StatelessWidget {
final String text;
final int count;
const CardCount({
super.key,
required this.text,
required this.count,
});
@override
Widget build(BuildContext context) {
return Card(
elevation: 20,
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
text,
style: Theme.of(context)
.textTheme
.headlineLarge
?.copyWith(color: Colors.brown, fontWeight: FontWeight.w900),
),
Text(
count.toString(),
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
);
}
}
class TimerCard extends StatefulWidget {
const TimerCard({super.key});
@override
State<TimerCard> createState() => _TimerCardState();
}
class _TimerCardState extends State<TimerCard> {
int count = 0;
@override
void initState() {
super.initState();
Timer.periodic(
const Duration(seconds: 1),
(timer) {
count += 1;
setState(() {});
},
);
}
@override
Widget build(BuildContext context) {
return Card(
clipBehavior: Clip.antiAlias,
child: Container(
padding: const EdgeInsets.all(20),
color: Colors.green,
height: 50 + count * 5,
child: Text(
count.toString(),
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
color: Colors.white,
fontWeight: FontWeight.w900,
),
),
),
);
}
}
@codesxt
Copy link
Author

codesxt commented Oct 4, 2023

Este código ejemplifica la aplicación de temas globales y locales en la app. También ejemplifica el uso de Widgets tipo Stateless y Stateful en distintos contextos.

El Widget Stateless se llama CardCount. Este Widget recibe como parámetros una String y un int y los usa para mostrar el conteo de clicks realizado por el usuario al presionar el FAB (Floating Action Button). Cada vez que estos parámetros se modifican, el Widget CardCount es reemplazado rápidamente por otra instancia con los nuevos valores dando la ilusión de que sólo cambió el contador.

El Widget Stateful se llama TimerCard. Este Widget no recibe ningún parámetro, pero mantiene dentro de su estado un contador int que se inicializa en 0. En el método de ciclo de vida initState, que permite ejecutar código en la inicialización del Widget, se inicializa un Timer (de la biblioteca dart:async) que ejecuta una función una vez por segundo. En esta función se actualiza el valor de count y mediante el llamado a setState se notifica que el estado del Widget cambió. Esto hace que el Widget vuelva a llamar a la función build para redibujarse. En la función build se escribe el contador como String con counter.toString() pero también se usa para calcular la altura del Container que incluye esta variable para evidenciar que el estado puede usarse para modificar otras propiedades de los Widgets además del texto.

@codesxt
Copy link
Author

codesxt commented Oct 4, 2023

Acá una vista previa de la aplicación:

Screenshot_1696441129

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment