
Yes No – Maybe App
Empezamos creando un nuevo proyecto para Flutter al cual le vamos a llamar yes_no_app
en nuestro main.dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Yes No App',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Material App Bar'),
),
body: Center(
child: FilledButton.tonal(
onPressed: () { },
child: const Text('Click me')
),
),
),
);
}
}
Estilos globales de la aplicación
Empezamos creando nuestro archivo de themes, para ello lo vamos a importar con:
debugShowCheckedModeBanner: false,
theme: AppTheme(selectedColor: 6).theme(),
se va a ubicar en: /lib/config/theme/app_theme.dart
import 'package:flutter/material.dart';
const Color _customColor = Color(0xFF5C11D4);
const List<Color> _colorThemes = [
_customColor,
Colors.blue,
Colors.teal,
Colors.green,
Colors.yellow,
Colors.orange,
Colors.pink,
];
class AppTheme {
final int selectedColor;
AppTheme({this.selectedColor = 0})
: assert(selectedColor >= 0 && selectedColor <= _colorThemes.length - 1,
'Color must be between 0 amd ${_colorThemes.length}');
ThemeData theme() {
return ThemeData(
useMaterial3: true,
colorSchemeSeed: _colorThemes[selectedColor],
);
}
}
Chat Screen
Vamos a usarlo como home y vamos a crear el archivo /lib/presentation/chat/chat_screen.dart
import 'package:flutter/material.dart';
class ChatScreen extends StatelessWidget {
const ChatScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: const Padding(
padding: EdgeInsets.all(4.0),
child: CircleAvatar(
backgroundImage: NetworkImage('https://styles.redditmedia.com/t5_2rfvv/styles/communityIcon_z02r4yt62j461.jpg'),
),
),
title: const Text('Mi amor 💖'),
centerTitle: false,
),
);
}
}
Ahora vamos a agregar nuestro body
Al build vamos a crear el body
body: _ChatView(),
y creamos nuestro widget
class _ChatView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: [
Expanded(child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return Text('Indice: $index');
},
)),
Text('Mundo')
],
),
),
);
}
}
Mensajes
vamos a crear nuestro chat en: /lib/presentation/widgets/chat/my_message_bubble.dart
import 'package:flutter/material.dart';
class MyMessageBubble extends StatelessWidget {
const MyMessageBubble({super.key});
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
decoration: BoxDecoration(
color: colors.primary, borderRadius: BorderRadius.circular(20)),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Text(
'Laboris duis dolore',
style: TextStyle(color: Colors.white),
),
),
),
const SizedBox(height: 10)
],
);
}
}
Mensaje de Respuesta:
import 'package:flutter/material.dart';
class HerMessageBubble extends StatelessWidget {
const HerMessageBubble({super.key});
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: colors.secondary, borderRadius: BorderRadius.circular(20)),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Text(
'Hello World',
style: TextStyle(color: Colors.white),
),
),
),
const SizedBox(height: 5),
_ImageBuble(),
const SizedBox(height: 10),
],
);
}
}
class _ImageBuble extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.network(
'https://yesno.wtf/assets/no/19-2062f4c91189b1f88a9e809c10a5b0f0.gif',
width: size.width * 0.7,
height: 150,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Container(
width: size.width * 0.7,
height: 150,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: const Text('Mi amor esta enviando una imagen'),
);
},
));
}
}
TextForm Field
Vamos a crear: /lib/presentation/widgets/shared/message_field_box.dart
import 'package:flutter/material.dart';
class MessageFieldBox extends StatelessWidget {
const MessageFieldBox({super.key});
@override
Widget build(BuildContext context) {
final textController = TextEditingController();
final focusNode = FocusNode();
final outlineInputBorder = UnderlineInputBorder(
borderSide: const BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.circular(40));
final inputDecoration = InputDecoration(
hintText: 'End your message with a "?"',
enabledBorder: outlineInputBorder,
focusedBorder: outlineInputBorder,
filled: true,
suffixIcon: IconButton(
icon: const Icon(Icons.send_outlined),
onPressed: () {
final textValue = textController.value.text;
print('button: $textValue');
},
));
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
child: TextFormField(
onTapOutside: (event) {
focusNode.unfocus();
},
focusNode: focusNode,
controller: textController,
decoration: inputDecoration,
onFieldSubmitted: (value) {
print('Submit vale $value');
textController.clear();
focusNode.requestFocus();
},
),
);
}
}