Pista de máximo a mínimo y lista de mensajes implementada

parent 116b05cb
......@@ -43,3 +43,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
/android/app/.cxx
import 'package:flutter/material.dart';
import 'package:peponator/widgets/peponator_mensaje.dart';
import 'dart:math';
import 'package:peponator/widgets/teclado_numerico.dart';
import 'package:peponator/widgets/tu_mensaje.dart';
class PantallaJuego extends StatefulWidget {
const PantallaJuego({super.key});
......@@ -11,35 +13,49 @@ class PantallaJuego extends StatefulWidget {
}
class _PantallaJuegoState extends State<PantallaJuego> {
late final TextEditingController controller = TextEditingController();
late final TextEditingController textController = TextEditingController();
late final ScrollController scrollController = ScrollController();
late final int numeroAdivinar;
late final List<String> pistas;
List<Widget> mensajes = [];
late final List<Widget> pistas = [];
late int limiteInferior;
late int limiteSuperior;
int? numeroEscogido;
bool mostrarPistas = false;
@override
void initState() {
super.initState();
Random random = new Random();
limiteInferior = 0;
limiteInferior = 1;
// TODO: Cargar el límite superior
limiteSuperior = 100;
numeroAdivinar = random.nextInt(limiteSuperior)+1;
numeroAdivinar = random.nextInt(limiteSuperior)+limiteInferior;
mensajes.add(PeponatorMensaje(message: "¡Hola! Estoy pensando en un número del ${limiteInferior} al ${limiteSuperior}. ¿Te crees capaz de adivinarlo?"));
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: (mostrarPistas)? Theme.of(context).colorScheme.surfaceDim : null,
body: SafeArea(
child: Stack(
children: [
Positioned(
top: 0,
left: 0,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 400,
child: (mostrarPistas)? _buildVistaPistas() : _buildVistaMensajes()
)
),
Positioned(
top: 0,
right: 10,
child: ElevatedButton(
onPressed: () {
......@@ -75,12 +91,55 @@ class _PantallaJuegoState extends State<PantallaJuego> {
);
}
void _scrollDown() {
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
);
}
Widget _buildVistaMensajes(){
return ListView.builder(
itemBuilder: (context, item) {
return mensajes[item];
},
controller: scrollController,
itemCount: mensajes.length,
shrinkWrap: true,
);
}
Widget _buildVistaPistas(){
return ListView.builder(
itemBuilder: (context, item) {
return pistas[item];
},
controller: scrollController,
itemCount: pistas.length,
shrinkWrap: true,
);
}
Widget _buildTeclado() {
final fullWidth = MediaQuery.of(context).size.width;
final fullHeight = 360.0;
final fullHeight = 380.0;
return Container(
//color: Theme.of(context).colorScheme.surfaceDim,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
Theme.of(context).colorScheme.surface,
Theme.of(context).colorScheme.surface.withAlpha(0)
],
stops: <double>[
0.97,
1.0
]
)
),
child: Column(
children: [
SizedBox(
......@@ -90,9 +149,45 @@ class _PantallaJuegoState extends State<PantallaJuego> {
children: [
SizedBox(
width: fullWidth/4,
child: IconButton(
onPressed: () {},
style: ButtonStyle(
child: _buildHintToggleButton()
),
SizedBox(
width: fullWidth*3/4,
child: _buildTextDisplay()
)
],
),
),
SizedBox(
width: fullWidth,
height: fullHeight*3/4,
child: Row(
children: [
SizedBox(
width: fullWidth/4,
child: _buildBoundsDisplay()
),
SizedBox(
width: fullWidth*3/4,
child: TecladoNumerico(
onNumberPress: _onNumberPress,
onBackspacePress: _onBackspacePress,
onEnterPress: _onEnterPress,
),
)
],
),
)
],
),
);
}
Widget _buildHintToggleButton(){
final onPressed = () => setState(() {
mostrarPistas = !mostrarPistas;
});;
const style = ButtonStyle(
shape: WidgetStatePropertyAll<OutlinedBorder>(CircleBorder()),
padding: WidgetStatePropertyAll<EdgeInsets>(
EdgeInsets.all(16.0)
......@@ -103,7 +198,22 @@ class _PantallaJuegoState extends State<PantallaJuego> {
color: Colors.black12
)
)
);
if(mostrarPistas){
return IconButton.filled(
onPressed: onPressed,
style: style,
icon: const Icon(
Icons.lightbulb,
size: 35.0,
),
);
}
return IconButton(
onPressed: onPressed,
style: style,
icon: Badge(
label: Text(
'!',
......@@ -119,46 +229,160 @@ class _PantallaJuegoState extends State<PantallaJuego> {
size: 35.0,
),
)
),
),
SizedBox(
width: fullWidth*3/4,
child: ExcludeFocus(
);
}
Widget _buildTextDisplay(){
return ExcludeFocus(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: TextField(
controller: controller,
controller: textController,
enableInteractiveSelection: false,
textAlign: TextAlign.end,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
decoration: const InputDecoration(
hintText: 'Tu respuesta...',
border: OutlineInputBorder()
),
),
),
);
}
Widget _buildBoundsDisplay(){
double? gradient;
if(numeroEscogido != null &&
numeroEscogido! <= limiteSuperior &&
numeroEscogido! >= limiteInferior) {
gradient = (1-(numeroEscogido! - limiteInferior)/(limiteSuperior - limiteInferior));
print(gradient);
}
return Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Máximo',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Colors.red,
fontWeight: FontWeight.bold,
)
),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
child: Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.red,
width: 3.0
),
borderRadius: BorderRadius.all(Radius.circular(16.0))
)
),
child: Text(
limiteSuperior.toString(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
),
)
]
),
Expanded(
child: Container(
width: 16.0,
decoration: (gradient != null)?
BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Colors.lightBlue.shade900,
Colors.lightBlue,
],
stops: <double>[
(gradient - 0.05 < 0.0)? 0.0 : gradient - 0.05,
(gradient + 0.05 > 1.0)? 1.0 : gradient + 0.05,
]
)
) :
BoxDecoration(
color: Colors.grey
),
)
),
SizedBox(
width: fullWidth,
height: fullHeight*3/4,
child: Row(
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: fullWidth/4,
child: Placeholder(),
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green,
width: 3.0
),
SizedBox(
width: fullWidth*3/4,
child: TecladoNumerico(controller: controller),
borderRadius: BorderRadius.all(Radius.circular(16.0))
)
],
),
child: Text(
limiteInferior.toString(),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
),
),
Text(
'Mínimo',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w800,
color: Colors.green
)
],
),
]
)
],
);
}
void _onNumberPress(int number){
setState(() {
numeroEscogido ??= 0;
numeroEscogido = numeroEscogido!*10 + number;
if(numeroEscogido == 0) numeroEscogido = null;
textController.text = numeroEscogido?.toString() ?? "";
});
}
void _onBackspacePress(){
setState(() {
numeroEscogido ??= 0;
numeroEscogido = (numeroEscogido!/10).floor();
if(numeroEscogido == 0) numeroEscogido = null;
textController.text = numeroEscogido?.toString() ?? "";
});
}
void _onEnterPress(){
final initialMaxScrollExtent =
scrollController.position.maxScrollExtent;
setState(() {
if(numeroEscogido != null && numeroEscogido! >= limiteInferior && numeroEscogido! <= limiteSuperior){
mensajes.add(TuMensaje(message: numeroEscogido.toString()));
mensajes.add(PeponatorMensaje(message: "¡Hola! Estoy pensando en un número del ${limiteInferior} al ${limiteSuperior}. ¿Te crees capaz de adivinarlo?"));
numeroEscogido = null;
textController.text = "";
}
});
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollDown();
});
}
}
import 'package:flutter/material.dart';
import 'dart:math';
class PeponatorMensaje extends StatelessWidget {
final String message;
const PeponatorMensaje({
Key? key,
required this.message,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final messageTextGroup = Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
flex: 20,
child: ClipRRect(
borderRadius: BorderRadius.circular(50.0), //add border radius
child: Image.network(
"https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg",
height: 80.0,
width: 80.0,
fit:BoxFit.cover,
),
)
),
const SizedBox(width: 12.0,),
Transform(
alignment: Alignment.center,
transform: Matrix4.rotationY(pi),
child: CustomPaint(
painter: _Triangle(Colors.grey.shade300),
),
),
Flexible(
flex: 45,
child: Container(
padding: EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.only(
topRight: Radius.circular(18),
bottomLeft: Radius.circular(18),
bottomRight: Radius.circular(18),
),
),
child: Text(
message,
style: TextStyle(color: Colors.black, fontFamily: 'Monstserrat', fontSize: 14),
),
),
),
],
)
);
return Padding(
padding: EdgeInsets.only(right: 60.0, left: 18.0, top: 5.0, bottom: 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(height: 30),
messageTextGroup,
],
),
);
}
}
class _Triangle extends CustomPainter {
final Color bgColor;
_Triangle(this.bgColor);
@override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = bgColor;
var path = Path();
path.lineTo(-5, 0);
path.lineTo(0, 10);
path.lineTo(5, 0);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
\ No newline at end of file
import 'package:flutter/material.dart';
typedef NumberCallback = void Function(int number);
class TecladoNumerico extends StatelessWidget {
final TextEditingController controller;
final NumberCallback? onNumberPress;
final VoidCallback? onBackspacePress;
final VoidCallback? onEnterPress;
final Color numberBackgroundColor;
......@@ -14,11 +17,12 @@ class TecladoNumerico extends StatelessWidget {
const TecladoNumerico({
Key? key,
required this.controller,
this.onNumberPress,
this.onBackspacePress,
this.onEnterPress,
this.numberBackgroundColor = Colors.cyan,
this.backspaceBackgroundColor = Colors.red,
this.enterBackgroundColor = Colors.lightGreen,
this.enterBackgroundColor = Colors.green,
this.numberColor = const Color.fromARGB(255, 255, 255, 255),
this.backspaceColor = const Color.fromARGB(255, 255, 255, 255),
this.enterColor = const Color.fromARGB(255, 255, 255, 255),
......@@ -80,7 +84,9 @@ class TecladoNumerico extends StatelessWidget {
),
),
onPressed: () {
controller.text += number.toString();
if(onNumberPress != null){
onNumberPress!(number);
}
},
child: Text(
number.toString(),
......@@ -106,11 +112,7 @@ class TecladoNumerico extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(16.0))
)
),
onPressed: () {
if(controller.text.isNotEmpty){
controller.text = controller.text.substring(0, controller.text.length-1);
}
},
onPressed: onBackspacePress,
child: Icon(
Icons.backspace_outlined,
color: backspaceColor,
......
import 'package:flutter/material.dart';
import 'dart:math';
class TuMensaje extends StatelessWidget {
final String message;
const TuMensaje({
Key? key,
required this.message
}): super(key: key);
@override
Widget build(BuildContext context) {
final messageTextGroup = Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Container(
padding: EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.blueAccent.shade400,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(18),
bottomLeft: Radius.circular(18),
bottomRight: Radius.circular(18),
),
),
child: Text(
message,
style: TextStyle(color: Colors.white, fontFamily: 'Monstserrat', fontSize: 18),
),
),
),
CustomPaint(painter: _Triangle(Colors.blueAccent.shade400)),
],
));
return Padding(
padding: EdgeInsets.only(right: 18.0, left: 50, top: 5, bottom: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(height: 30),
messageTextGroup,
],
),
);
}
}
class _Triangle extends CustomPainter {
final Color bgColor;
_Triangle(this.bgColor);
@override
void paint(Canvas canvas, Size size) {
var paint = Paint()..color = bgColor;
var path = Path();
path.lineTo(-5, 0);
path.lineTo(0, 10);
path.lineTo(5, 0);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment