Last active
April 19, 2025 14:55
-
-
Save Klerith/85fe516a31580bd2b9d6090002ee3d24 to your computer and use it in GitHub Desktop.
Pantalla de edición y creación de imágenes con Gemini
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://gist.github.com/Klerith/85fe516a31580bd2b9d6090002ee3d24 | |
import 'package:flutter/material.dart'; | |
import 'package:image_picker/image_picker.dart'; | |
import 'package:gemini_chat/config/theme/app_theme.dart'; | |
import 'package:gemini_chat/presentation/widgets/chat/custom_bottom_input.dart'; | |
const imageArtStyles = [ | |
'Realista', | |
'Acuarela', | |
'Dibujo a Lápiz', | |
'Arte Digital', | |
'Pintura al Óleo', | |
'Acuarela', | |
'Dibujo al Carboncillo', | |
'Ilustración Digital', | |
'Estilo Manga', | |
]; | |
class ImagePlaygroundScreen extends StatelessWidget { | |
const ImagePlaygroundScreen({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Imágenes con Gemini')), | |
backgroundColor: seedColor, | |
body: Column( | |
children: [ | |
// Espacio para imágenes generadas | |
GeneratedImageGallery(), | |
// Selector de estilo de arte | |
ArtStyleSelector(), | |
// Llenar el espacio | |
Expanded(child: Container()), | |
// Espacio para el prompt | |
CustomBottomInput( | |
onSend: (p0, {List<XFile> images = const []}) { | |
// Todo: | |
}, | |
), | |
], | |
), | |
); | |
} | |
} | |
class GeneratedImageGallery extends StatelessWidget { | |
const GeneratedImageGallery({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return SizedBox( | |
height: 250, | |
child: PageView( | |
controller: PageController( | |
viewportFraction: 0.6, // Muestra 1.5 imágenes en la pantalla | |
initialPage: 0, | |
), | |
padEnds: true, // Cambiado a true para centrar la primera imagen | |
children: [ | |
//* Placeholder hasta que se genere al menos una imagen | |
const EmptyPlaceholderImage(), | |
const GeneratingPlaceholderImage(), | |
//* Aquí iremos colocando las imágenes generadas | |
GeneratedImage( | |
imageUrl: | |
'https://www.theclickcommunity.com/blog/wp-content/uploads/2018/04/woman-with-red-hair-outside-by-Cassandra-Casley.jpg', | |
), | |
GeneratedImage( | |
imageUrl: | |
'https://www.theclickcommunity.com/blog/wp-content/uploads/2018/04/woman-with-red-hair-outside-by-Cassandra-Casley.jpg', | |
), | |
], | |
), | |
); | |
} | |
} | |
class GeneratedImage extends StatelessWidget { | |
final String imageUrl; | |
const GeneratedImage({super.key, required this.imageUrl}); | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
width: 200, | |
height: 200, | |
margin: const EdgeInsets.all(10), | |
decoration: BoxDecoration( | |
color: Colors.blue, | |
borderRadius: BorderRadius.circular(10), | |
boxShadow: [ | |
BoxShadow( | |
color: Colors.black.withValues(alpha: 0.3), | |
blurRadius: 5, | |
spreadRadius: 5, | |
offset: Offset(0, 0), | |
), | |
], | |
), | |
child: ClipRRect( | |
borderRadius: BorderRadius.circular(10), | |
child: Image.network(imageUrl, fit: BoxFit.cover), | |
), | |
); | |
} | |
} | |
class ArtStyleSelector extends StatelessWidget { | |
const ArtStyleSelector({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return SizedBox( | |
height: 50, | |
child: ListView.builder( | |
scrollDirection: Axis.horizontal, | |
itemCount: imageArtStyles.length, | |
itemBuilder: (context, index) { | |
final style = imageArtStyles[index]; | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 4.0), | |
child: Chip( | |
label: Text(style), | |
backgroundColor: Theme.of(context).colorScheme.primaryContainer, | |
), | |
); | |
}, | |
), | |
); | |
} | |
} | |
class EmptyPlaceholderImage extends StatelessWidget { | |
const EmptyPlaceholderImage({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
width: 200, | |
height: 200, | |
margin: const EdgeInsets.all(10), | |
decoration: BoxDecoration( | |
color: Colors.deepPurple, | |
borderRadius: BorderRadius.circular(10), | |
border: Border.all(color: Colors.white, width: 2), | |
boxShadow: [ | |
BoxShadow( | |
color: Colors.black.withValues(alpha: 0.3), | |
blurRadius: 5, | |
spreadRadius: 5, | |
offset: Offset(0, 0), | |
), | |
], | |
), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
const Icon(Icons.image_outlined, size: 50, color: Colors.white), | |
const Text('Empieza a generar imágenes'), | |
], | |
), | |
); | |
} | |
} | |
class GeneratingPlaceholderImage extends StatelessWidget { | |
const GeneratingPlaceholderImage({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
width: 200, | |
height: 200, | |
margin: const EdgeInsets.all(10), | |
decoration: BoxDecoration( | |
color: Colors.deepPurple, | |
borderRadius: BorderRadius.circular(10), | |
border: Border.all(color: Colors.white, width: 2), | |
boxShadow: [ | |
BoxShadow( | |
color: Colors.black.withValues(alpha: 0.3), | |
blurRadius: 5, | |
spreadRadius: 5, | |
offset: Offset(0, 0), | |
), | |
], | |
), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
const CircularProgressIndicator(color: Colors.white, strokeWidth: 3), | |
const SizedBox(height: 15), | |
const Text( | |
'Generando imagen...', | |
style: TextStyle(color: Colors.white), | |
), | |
], | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment