Decidí hacer que la valoración de estrellas fuera más dinámica según la puntuación dada.
Bienvenida e Introducción
¡Renovaremos este curso!
Desarrollando en Flutter
¿Qué es Flutter?
Dart y Flutter
Sintaxis de Dart
¡Renovaremos este curso!
Flutter para desarrolladores Android, iOS y Xamarin.forms
Flutter para desarrolladores React Native
¿Cómo luce una app construída en Flutter?
Primer reto
Creando mi entorno de desarrollo
¡Renovaremos este curso!
Requerimientos de Hardware y Software
Instalando Flutter en Android Studio y Visual Studio Code
Composición de un proyecto en Flutter
Interfaces en Flutter
¡Renovaremos este curso! Te quedan unos días para concluirlo.
Programación Declarativa en Flutter
Estructura de un programa en Flutter
Hola Mundo en Flutter
Widgets básicos
Widgets con estado y sin estado
Análisis de Interfaces de Usuario en Flutter
Definiendo los layouts de nuestra interfaz
Segundo reto
Widgets sin estado en Flutter
¡Renovaremos este curso! Te quedan unos días para concluirlo.
Flutter Widgets: Container, Text, Icon, Row
Flutter Widgets: Column
Recursos en Flutter: Tipografías y Google Fonts
Widget Image
Widget Apilando Textos
Widgets Decorados
Widget Imagen Decorada
Widget Listview
Widget Button, InkWell
Tercer reto
Widgets con estado en Flutter
¡Renovaremos este curso! Te quedan unos días para concluirlo.
Botones en Flutter
Clase StatefulWidget: Cómo se compone
Widget Floating Action Button
Widgets BottomNavigationBar
Generando Navegación en BottomNavigationBar
Personalizando nuestro BottomNavigation Bar a Cupertino iOS BottomBar
Cuarto reto
Fin del Curso
¡Renovaremos este curso!
Conclusiones
¡Terminamos!
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Anahí Salgado Díaz de la Vega
El widget Column, como ya vimos, nos permite organizar distintos elementos visuales de la interfaz (también widgets) de manera vertical, alineados uno arriba / debajo del otro en el eje Y.
Los widgets hijos, que van a ser organizados dentro de un Column padre, deben estar definidos en la propiedad children
de éste, como un arreglo de elementos de tipo
.
Algo que debemos recordar es que los widgets que usamos como children
, pueden definirse bien sea directamente (inline) o bien a través de clases externas (o widgets personalizados) que hemos definido previamente en archivos .dart independientes.
Para utilizar valores que nos permitan tener contenido dinámico en nuestra interfaz es necesario apoyarnos en el método constructor
que lleva el mismo nombre de la clase y en el que definimos los parámetros de entrada que serán utilizados en lugar de las variables por defecto que también hemos definido antes.
Aportes 104
Preguntas 28
Decidí hacer que la valoración de estrellas fuera más dinámica según la puntuación dada.
me tome el tiempo de comentar todo el codigo aqui el icono que escogi fue el favorite
import 'package:flutter/material.dart';//Nos habilita los witgets los elementos que estaremos trabajando en esta interface
//
class DescripcionLugar extends StatelessWidget {
//class: crea una clase, extends: heredar, //StatelessWidget(widget sin estado: seran aquellos que se heredan de la clase StatelessWidget. son elementos fijos que no interactuan con el usuario ejemplo: icono, texto, contenedor con color )
@override
Widget build(BuildContext context) {
//metodo build:es el metodo que construye la interface, construye el widget con los elementos que estaremos trabajando
final estrella_sincolor = Container(//Container:tendra la estrella y le pondremos margenes para acomodar la estrella sin color en este caso
margin: EdgeInsets.only(// EdgeInsets.only(), esto me permite generar un margen mas especifico a nivel de top, left, right, bottom
//margin: margenes de nuestros elementos del container
top: 349.0,//arriba
right: 3.0,//derecha
),
child: Icon(//child toma un solo widget toma un solo elemnto, en este caso toma el icono "estrella"
Icons.favorite_border,//widget icono estrella con color a los bordes
color: Color(0xFFF06A66),//propiedad color que lleva un widged llamado: Color para darle color a nuestro icono.
)
);
final estrella = Container(//Container:tendra las estrellas y le pondremos margenes para acomodar la estrella con color
margin: EdgeInsets.only(// EdgeInsets.only(), esto me permite generar un margen mas especifico a nivel de top, left, right, bottom
//margin: margenes de nuestros elementos del container
top: 349.0,//arriba
right: 3.0,//derecha
),
child: Icon(//child toma un solo widget toma un solo elemnto, en este caso toma el icono "estrella"
Icons.favorite,//widget icono estrella
color: Color(0xFFF06A66),//propiedad color que lleva un widged llamado: Color para darle color a nuestro icono. (0xFFf2C611): esto son colores hexagecimal
),
);
final descripcion = Container(//final: significa asignación simple: una variable o campo final * debe * tener un inicializador. Una vez asignado un valor, el valor de una variable final no se puede cambiar. Modificaciones finales * variables *.
margin: EdgeInsets.only(// EdgeInsets.only(), esto me permite generar un margen mas especifico a nivel de top, left, right, bottom
//margin: margenes de nuestros elementos del container
top: 15.0,//arriba
left: 20.0,//izquierda
right: 20.0,//derecha
),
child: Text(//child(Hijo) toma un solo widget toma un solo elemnto. Text: widget de elementos tipo texto
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut semper ornare sodales. Cras condimentum enim purus, sed placerat nunc volutpat et. Nunc malesuada, quam vel consectetur convallis, libero nisi volutpat nibh, ut aliquet diam eros eu tortor. Cras eget accumsan purus. Quisque sed justo convallis, efficitur ipsum sed, hendrerit nisl. \nDuis tincidunt, est vitae molestie laoreet elit dolor varius dui, ac malesuada ex orci vel libero.",
style: TextStyle(//propiedad style: darle estilo a un elemento. widget TextStyle: darle estilos a un elemento tipo texto
color: Color(0xFF56575a)//color al texto
),
textAlign: TextAlign.justify//alineamos el parrafo con un espacio justificado
),
);
final titulo_estrellas = Row( //final: significa asignación simple: una variable o campo final * debe * tener un inicializador. Una vez asignado un valor, el valor de una variable final no se puede cambiar. Modificaciones finales * variables *.
//row: Un row, es un widget que se utiliza para mostrar widgets de forma horizontal. El widget row no se desplaza. Si tiene una línea de widgets y desea que puedan desplazarse si no hay suficiente espacio, considere usar una Clase ListView.
children: <Widget>[//children: lleva una lista de widgets, lleva una lista de elementos, children:seran todos elementos que estan apilados en forma de Row(fila) o renglon
Container( //Container:tendra el texo y le pondremos margenes para acomodar la informacion
margin: EdgeInsets.only( // EdgeInsets.only(), esto me permite generar un margen mas especifico a nivel de top, left, right, bottom
//margin: margenes de nuestros elementos del container
top: 345.0, //arribae
left: 25.0, //izquierda
right: 26.0 //derecha
),
child: Text( //child toma un solo widget toma un solo elemnto. Text: widget de elementos tipo texto
"Duwili Ella",//texto
style: TextStyle( //propiedad style: darle estilo a un elemento. widget TextStyle: darle estilos a un elemento tipo texto
fontSize: 30.0, //propiedad fontSize para canbiar tamaño del titulo
fontWeight: FontWeight.w900 //fontWeight es una propiedad. FontWeight.w900 es un widget para darle Negrita como en word
),
textAlign: TextAlign.left, //propiedad textAlign: para alinear textos. TextAlign.left: es un widget para alinear textos a la izquierda
),
),
Row(//acomoda los elemendos en fila en este caso estrellas
children: <Widget>[//tomamos varios hijos o widgets y los ponemos dentro de una fila
//Aqui llamamos los hijos, elementos o widgets que queremos que se muestren en pantalla ↓↓↓(las veces que queramos)
estrella,//llamamos al primer hijo(widget)
estrella,//llamamos al segundo hijo(widget)
estrella,//llamamos al tercero hijo(widget)
estrella,//llamamos al cuarto hijo(widget)
estrella_sincolor,//llamamos al quinto hijo(widget)
],
),
],
);
return Column(//retomamos los elementos y los pone en una columna
children: <Widget>[//tomamos varios hijos o widgets y los ponemos dentro de una columna
titulo_estrellas,//llamamos al primer hijo(widget)
descripcion,//llamamos al segundo hijo(widget)
],
);
}
}
Partiendo de la aportación de uno de mis compañeros, agregué la validación sólo para el widget de Icon, además de contemplar rating con decimales (ejemplo rating 4.5).
Widget starsWidget(double numberOfStars){
List<Widget> rowStars = [];
for(int i=1; i<=5; i++){
rowStars.add(starWidget(numberOfStars));
numberOfStars--;
}
return new Row(
children: rowStars,
);
}
Widget starWidget(double numberOfStars){
return new Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: validateStarIconWidget(numberOfStars),
);
}
Widget validateStarIconWidget(double numberOfStars){
if(numberOfStars >= 1.0){
return fullStarIconWidget();
}
if(numberOfStars >= 0.5){
return halfStarIconWidget();
}
return emptyStarIconWidget();
}
Widget fullStarIconWidget(){
return new Icon(
Icons.star,
color: Color(0XFFF2C611),
);
}
Widget halfStarIconWidget(){
return new Icon(
Icons.star_half,
color: Color(0XFFF2C611),
);
}
Widget emptyStarIconWidget(){
return new Icon(
Icons.star_border,
color: Color(0XFFF2C611),
);
}
✨ Aplicación en desarrollo.
Cuál es la diferencia entre
new Text(dummyDescription)
y
Text(dummyDescription)
¿?
Traté de replicar lo del video, pero parece en 2022 las cosas ya no se hacen de esta forma, cuando logre ver como se hace volveré con la respuesta… Creo 😅
Hecho 😃
Para las estrellas de forma dinámica con calificaciones de enteras y con decimales yo lo resolví de la siguiente manera:
List<Widget> starWidgetArrray = [];
int starInteger = stars.toInt();
bool starHalf = !stars.toString().contains('.0');
for(int i = 1; i <= 5; i++){
if(i <= starInteger){
starWidgetArrray.add(star);
}else if(i == starInteger+1 && starHalf) {
starWidgetArrray.add(star_half);
}else {
starWidgetArrray.add(star_border);
}
}
Claro que el argumento star del widget lo declaré como double en lugar de int.
Finalmente, en el row para las estrellas en el atributo children solo le paso el array de estrella que se generó dinámicamente.
Row(
children: starWidgetArrray
)
Creo que es la solución más optima que encontré, la variable numberOfStars admite decimales y de acuerdo a ello genera las estrellas.
Comparto aqui mi solución para pintar las estrellas según el puntaje dado como parámetro all Widget compuesto en main.dart
import 'package:flutter/material.dart';
class informacion_detalle extends StatelessWidget {
/*
* variables de la clase
* */
double puntuacion;
String descripcion;
String titulo_lugar;
/*
* constructor
* */
informacion_detalle(this.titulo_lugar, this.descripcion, this.puntuacion);
@override
Widget build(BuildContext context) {
/*
* creando la declaracion del widget titulo y asignando a variable para luego ser utilizado
* */
var titulo = Container(
margin: EdgeInsets.only(top: 320, left: 20, right: 20),
child: Text(titulo_lugar,
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), textAlign: TextAlign.left),
);
/*
* creando la declaracion del widget detalle y asignando a variable
* */
final detalle = Container(
margin: EdgeInsets.only(left: 20, right: 20, top: 20),
child: Text(descripcion,
textAlign: TextAlign.justify,
style: TextStyle(
color: Colors.black87,
fontSize: 18,
fontWeight: FontWeight.normal,
fontStyle: FontStyle.italic)),
);
/*
* creando la subvista con todos los widgets individuales anteriores
* */
final tituloANDpuntaje = Column(
children: <Widget>[
Row(
children: <Widget>[titulo, Row(children: printStars())],
),
detalle,
],
);
/*
* retornar el widget compuesto
* */
return tituloANDpuntaje;
}
/*
* creando la declaracion del widget estrella
* */
Widget create_star() {
var star = Container(
margin: EdgeInsets.only(top: 324, right: 3),
child: Icon(Icons.star, color: Colors.amber),
);
return star;
}
Widget create_emptyStar() {
var empty_star = Container(
margin: EdgeInsets.only(top: 324, right: 3),
child: Icon(Icons.star_border, color: Colors.amber),
);
return empty_star;
}
Widget create_halfStar() {
var half_star = Container(
margin: EdgeInsets.only(top: 324, right: 3),
child: Icon(Icons.star_half, color: Colors.amber),
);
return half_star;
}
/*
* funcion que imprime los Widgets estrella segun el puntaje
* */
List<Widget> printStars() {
List<Widget> estrellas = new List();
int rellenas = puntuacion.floor();
for (int i = 0; i < rellenas; i++) {
estrellas.add(create_star());
}
if (puntuacion - puntuacion.floor() != 0) {
estrellas.add(create_halfStar());
}
for (int i = 0; i < 5 - puntuacion.ceil(); i++) {
estrellas.add(create_emptyStar());
}
return estrellas;
}
}
Este es mi código un poco más dinámico:
Widget star(bool active){
return Container(
margin: EdgeInsets.only(
top: 323,
right: 3
),
child: Icon(
active ? Icons.star : Icons.star_border,
color: Color(0xFFf9da5e)
),
);
}
final titleElement = Row(
children: [
Container(
margin: EdgeInsets.only(
top: 320,
left: 20,
right: 20
),
child: Text(name, style: TextStyle(fontWeight: FontWeight.w900, fontSize: 21), textAlign: TextAlign.left)
),
Row(
children: [
for (int i = 0; i < 5; i++) star(stars > i ? true : false)
],
)
],
);
Les dejo como lo hize, para tener esto un poco mas dinamico
y aprender un poco mas de dart y como funcionan sus listas,
Widget start (bool onlyBorder) {
return Container(
margin: const EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: Icon(
onlyBorder ? Icons.star_border: Icons.star,
color: Color(0xFFf2C611),
),
);
}
Widget score (int totalStars, int score) {
return Row(
children: List.generate(totalStars, (index) {
return start(score < index);
}),
);
}
Implementacion
final titleStars = Row(
children: <Widget>[
Container(
margin: const EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0,
),
child: Text(
namePlace,
style: const TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900,
),
textAlign: TextAlign.left,
),
),
score(5, 3)
],
);
Comparto mi solución partiendo de la solución de unos de mis compañeros de usar un operador por cada fila agregando otra condición para poder usar la start_half
Row(
children: <Widget>[
stars < 1 && stars < 0.5 ? star_border : (stars < 1 && stars >= 0.5 ) ? star_half : star,
stars < 2 && stars < 1.5 ? star_border : (stars < 2 && stars >= 1.5 ) ? star_half : star,
stars < 3 && stars < 2.5 ? star_border : (stars < 3 && stars >= 2.5 ) ? star_half : star,
stars < 4 && stars < 3.5 ? star_border : (stars < 4 && stars >= 3.5 ) ? star_half : star,
stars < 5 && stars < 4.5 ? star_border : (stars < 5 && stars >= 4.5 ) ? star_half : star,
],
)
Aquí mi solución 😊:
Hice una widget con generación dinámica de estrellas que cálcula, construye y retorna el widget.
En vez de una constante o widget por tipo de estrella, hice una sola que genera los 3 tipos, llena (star), a la mitad (star_half) y vacía(star_border)
import 'package:flutter/material.dart';
class DescriptionPlace extends StatefulWidget {
final String textTitle;
final double countingStars;
final String textDescription;
const DescriptionPlace({
Key? key,
required this.textTitle,
required this.countingStars,
required this.textDescription
}) : super(key: key);
@override
State<DescriptionPlace> createState() => _DescriptionPlaceState();
}
class _DescriptionPlaceState extends State<DescriptionPlace> {
final double maxStars = 5.0;
final star = Container(
margin: const EdgeInsets.only(top:323.00, right: 3.00),
child: const Icon(
Icons.star,
color: Color(0xFFF2C611),
),
);
Widget starDrawing(int starType){
final starIcon = starType == 0 ? Icons.star_border: (starType == 1 ? Icons.star: Icons.star_half);
return Container(
margin: const EdgeInsets.only(top:323.00, right: 3.00),
child: Icon(
starIcon,
color: const Color(0xFFF2C611),
),
);
}
Widget showStars (double stars){
stars = stars > maxStars? maxStars: stars;
List<Widget> rowStars = [];
List<Widget> rowStarsHalf = [];
List<Widget> rowStarsBorder = [];
double totalStars = stars - (stars - stars.toInt());
double totalStarHalf = (stars - stars.toInt() > 0.0? 1: 0);
double totalStarBorder = maxStars - (stars + (stars - stars.toInt() < 0.0? 1: 0));
List.filled(totalStars.toInt(), null, growable: false).forEach((i) => rowStars.add(starDrawing(1)));
List.filled(totalStarHalf.toInt(), null, growable: false).forEach((i) => rowStarsHalf.add(starDrawing(2)));
List.filled(totalStarBorder.toInt(), null, growable: false).forEach((i) => rowStarsBorder.add(starDrawing(0)));
List<Widget> finalStars = []..addAll(rowStars)..addAll(rowStarsHalf)..addAll(rowStarsBorder);
return Row(children: finalStars);
}
@override
Widget build(BuildContext context) {
const marginTitle = EdgeInsets.only(top:320.00, left:20, right: 20.00);
const marginDescription = EdgeInsets.only(top:20.00, left:20.00, right: 20.00);
final description = Container(
margin: marginDescription,
child: Text(
widget.textDescription,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.left,
),
);
final titleStar = Row(
children: [
Container(
margin: marginTitle,
child: Text(
widget.textTitle,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.w900
),
),
),
showStars(widget.countingStars),
],
);
return Column(
children: [
titleStar,
description
],
);
}
}
}
Podemos hacer las estrellas dinámicas de la siguiente manera:
Luego sustituimos el raw con la lista de estrellas por la función colocaEstrellas, teniendo en cuenta que son solo 5 estrellas y no estrellas infinitas.
Esta fue mi solución para generar las estrellas dinámicamente dejando configurada una variable de maxStars para que pueda generar la cantidad de estrellas restantes, no sé si es lo mas optimo pero fue mi solución 😃
List<Widget> generateSatrtIcon(double total) {
print('total: ${total}');
List<Widget> starsIcons = [];
int totalInt = total.toInt();
print('total: ${totalInt}');
final startBorder = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: Icon(
Icons.star_border,
color: Color(0xFFf2C611),
),
);
final startHalf = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: Icon(
Icons.star_half,
color: Color(0xFFf2C611),
),
);
final start = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: Icon(
Icons.star,
color: Color(0xFFf2C611),
),
);
for(int i = 0; i < totalInt; i++) {
starsIcons.add(start);
}
if(total - totalInt > 0) {
starsIcons.add(startHalf);
}
if(5 - total > 1) {
for(int i = 0; i < 5 - totalInt; i++) {
starsIcons.add(startBorder);
}
}
return starsIcons;
}```
Mi solucion. La máxima cantidad de estrellas en pantalla siempre serán 5 y la estrella a la mitad solo se imprime cuando el decimal es superior a 0.4
import 'package:flutter/material.dart';
enum StarState {
filled, half, empty
}
class DescriptionPlace extends StatelessWidget {
String namePlace;
double stars;
String descriptionPlace;
DescriptionPlace(this.namePlace, this.stars, this.descriptionPlace);
@override
Widget build(BuildContext context) {
final titleStarts = Row(
children: <Widget> [
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0
),
child: Text(
this.namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left
)
),
Row(
children: this.getStars(this.stars)
)
]
);
final descriptionText = Container(
margin: EdgeInsets.only(
top: 16.0,
left: 20.0,
right: 20.0
),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
this.descriptionPlace,
style: TextStyle(
fontSize: 16.0,
color: Color.fromRGBO(51, 51, 51, .7)
),
textAlign: TextAlign.left
),
)
);
final mainContainer = Container(
child: Column(
children: <Widget>[
titleStarts,
descriptionText
]
)
);
return mainContainer;
}
List <Widget> getStars(double length) {
List <Widget> result = new List <Widget>();
if(length >= 5) {
result.addAll(
List.generate( 5, (_) => this.getStar(StarState.filled) )
);
} else {
int filledStars = length.floor();
double floatPoint = length - filledStars;
result.addAll(
List.generate( filledStars, (_) => this.getStar(StarState.filled) )
);
if(floatPoint > .4) {
result.add( this.getStar(StarState.half) );
}
int rest = 5 - result.length;
result.addAll(
List.generate( rest, (_) => this.getStar(StarState.empty) )
);
}
return result;
}
Widget getStar(StarState state) {
Icon starToUse;
Color amber = Color(0xFFF2C611);
switch( state ) {
case StarState.filled:
starToUse = Icon(
Icons.star,
color: amber
);
break;
case StarState.half:
starToUse = Icon(
Icons.star_half,
color: amber,
);
break;
case StarState.empty:
starToUse = Icon(
Icons.star_border,
color: Colors.grey,
);
break;
}
final star = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0
),
child: starToUse
);
return star;
}
}
En el widget sin estado DescriptionPlace, para que me funcionara tuve que agregar la propiedad final. Así:
Existe un children y un child …Alguien puede darme la diferencia y caso de uso? por favor.
el repositorio de git no existe
Mi solución:
import 'package:flutter/material.dart';
class DescriptionPlace extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
final star = Container(
margin: EdgeInsets.only(
top:323.0,
right: 3.0
),
child: Icon(
Icons.star,
color: Color(0xFFF2C716),
),
);
final title_stars = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0
),
child: Text(
"Duwili Ella",
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
),
),
Row(
children: <Widget>[
star,
star,
star,
star,
star
],
)
],
);
final descripction_text = Container(
margin: EdgeInsets.only(
top: 10.0,
left: 20.0,
right: 20.0,
bottom: 5.0
),
child: Text(
"Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
"Aenean commodo ligula eget dolor. Aenean massa."
"Cum sociis natoque penatibus et magnis dis parturient montes,"
"nascetur ridiculus mus. Donec quam felis, ultricies nec,"
"pellentesque eu",
style: TextStyle(
fontSize: 12.0,
color: Color(0xFF6D6E71)
),
textAlign: TextAlign.justify,
)
);
final _description_place = Column(
children: <Widget>[
title_stars,
descripction_text,
descripction_text
],
);
return _description_place;
}
}
Felicitaciones!
Buenas Noches
Una pregunta, al momento de crear un texto o un icono o cualquier otro widget, en que se basa uno para saber si lo debe de crear con la palabra new o sin ella, ya que veo que en el ejercicio en la creación del titulo lo utilizan sin la palabra new y en la descripción utilizan la palabra new.
final titulo = Container(
**child: new Text(**
'Dahyan Puerta',
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
),
margin: EdgeInsets.only(
left: 20.0,
top: 320.0,
right: 20.0
),
);
final titulo = Container(
**child: Text(**
'Dahyan Puerta',
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
),
margin: EdgeInsets.only(
left: 20.0,
top: 320.0,
right: 20.0
),
);
Mi implementación con título, texto y estrellas dinámicas:
import 'package:flutter/material.dart';
class DescriptionPlace extends StatelessWidget {
String namePlace;
String descriptionPlace;
num numStars;
List<Widget> starsList = [];
DescriptionPlace(this.namePlace, this.descriptionPlace, this.numStars);
@override
Widget build(BuildContext context) {
// TODO: implement build
final int fullStars = (numStars).floor();
final bool hasHalfedStars = numStars%1 != 0 ? true : false;
final int totalStars = (numStars).round();
final star_empty = Container(
margin: EdgeInsets.only(
top:323.0,
right: 3.0
),
child: Icon(
Icons.star_border,
color: Color(0xFFF2C716),
),
);
final star_half = Container(
margin: EdgeInsets.only(
top:323.0,
right: 3.0
),
child: Icon(
Icons.star_half,
color: Color(0xFFF2C716),
),
);
final star = Container(
margin: EdgeInsets.only(
top:323.0,
right: 3.0
),
child: Icon(
Icons.star,
color: Color(0xFFF2C716),
),
);
for(var i=0;i<fullStars;i++){
starsList.add(star);
}
if(hasHalfedStars){
starsList.add(star_half);
}
for(var i = totalStars; i < 5; i++){
starsList.add(star_empty);
}
final title_stars = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0
),
child: Text(
namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
),
),
Row(
children: starsList
)
],
);
final descripction_text = Container(
margin: EdgeInsets.only(
top: 10.0,
left: 20.0,
right: 20.0,
bottom: 5.0
),
child: Text(
descriptionPlace,
style: TextStyle(
fontSize: 12.0,
color: Color(0xFF6D6E71)
),
textAlign: TextAlign.justify,
)
);
final _description_place = Column(
children: <Widget>[
title_stars,
descripction_text,
descripction_text
],
);
return _description_place;
}
}
Agregué la la funcion star, para evitar duplicar código.
Recibe un IconData como parametro, esto me permite agregar el tipo de estrella deseado.
Ya para usar la half es otro codigo
for(var i = 0 ; i < starC ; i++)
stars,
for(var i = starC ; i < 5 ; i++)
stars_bordeer,
enum StarState {
none, half, filled
}
List <Widget> getStarRating(double stars){
List <Widget> starRating = new List <Widget>();
if(stars > 5){
stars = 5;
}
starRating.addAll(List.generate(stars.floor(), (_)=> getStar(StarState.filled)));
if(stars > stars.floor()) starRating.add(getStar(StarState.half));
if(starRating.length < 5) starRating.addAll(List.generate(5 - starRating.length, (_)=> getStar(StarState.none)));
return starRating;
}
Widget getStar(StarState state){
Icon star;
if(state == StarState.filled){
star = Icon(
Icons.star,
color: Color(0xFFF2C611),
);
} else if (state == StarState.half){
star = Icon(
Icons.star_half,
color: Color(0xFFF2C611)
);
}else {
star = Icon(
Icons.star_border,
color: Color(0xFFF2C611)
);
}
return Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3
),
child: star
);
}
Es conveniente Instanciar los Textos, margenes, etc?
o no es necesario?
Después de un ratote XD alfin hice lo que quería y todo por el
List<Widget> stars = new List<Widget>()
Widget getStars(double numberOfStars, {int maxStars:5}){
/*
This method return a row of stars
*/
List<Widget> stars = new List<Widget>();
int fullStars = numberOfStars.truncate();
int emptyStars = maxStars-fullStars;
double halfStars = numberOfStars % 1;
for (int iFull=0; iFull<fullStars; iFull+=1){
stars.add(star_full);
}
if (halfStars > 0.5){
stars.add(star_half);
emptyStars-=1;
}
for(int iEmpty = 0; iEmpty < emptyStars; iEmpty+=1){
stars.add(star_empty);
}
return new Row(
children: stars
);
}
final titleStars = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left:20.0,
right: 20.0,
),
child: Text(
namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
)
),
Container(
child: getStars(starsNum),
)
],
);
List<Widget> startsArray(num number) {
List<Widget> lista = new List.filled(5, start_border);
for(int i = 0; i < number; i++) {
lista[i] = start;
}
num difference = 5-number;
bool esEntero = number is int;
if( difference != 0 && !esEntero ) {
lista[number.toInt()] = start_half;
}
return lista;
}
Yo resolví el tema de las estrellas con una lista de widgets y una funcion que llena esa lista. Aclaro que mi puntuación la tomo de 1 a 50 con el objetivo de no tener que declararla double y usar decimales:
List<Widget> numberOfStars = new List<Widget>();
void setStars() {
for (int i = 0; i < this.stars / 10 - 1; i++) {
numberOfStars.add(star);
}
if (this.stars % 10 > 4) {
numberOfStars.add(star_half);
}
for (int i = numberOfStars.length; i < 5; i++) {
numberOfStars.add(star_border);
}
}
setStars();
Empecé hoy con Flutter así que no tengo demasiada idea, pero haciendo unas pruebas encontré esta solución que me parece interesante para no copiar y pegar 3 veces el icono de la estrella. Creé un único widget star al cual le paso como parámetro cuál de los 3 íconos posibles usar para c/estrella. Lo comparto por si a alguien le sirve:
Se crea el Widget _star
Widget _star(icon) {
// icon: indica el tipo de estrella, opciones: star, star_half, star_border
return Container(
margin: EdgeInsets.only(
right: 2.0,
top: 320.0
),
child: Icon(
icon,
color: Colors.amberAccent,
size: 16.0,
),
);
}
Se crea la lista de estrellas (un Widget lista) y se itera 5 veces (máximo de calificación posible) para ir agregando estrellas a la lista, c/una con su respectivo ícono según corresponda.
List <Widget> starsCalification = [];
for(var i = 0; i < 5; i++){
if(i <= stars && stars >= i+1){
starsCalification.add(_star(Icons.star));
} else if(i < stars){
starsCalification.add(_star(Icons.star_half));
} else{ starsCalification.add(_star(Icons.star_border)); }
}
Ahora que ya tenemos la lista, solo queda agregarla dentro del Row que contiene las reviews
final titleStars = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0
),
child: Text(
deviceName,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
),
),
Row(
children: starsCalification,
),
],
);
Resultado final
Contenido completo del fichero description_place.dart: https://drive.google.com/file/d/1natw4ufaR3PO-iTTrChzO3jtjoIcuNXH/view?usp=share_link
Les comparto mi Widget. Le agregué una lógica para completar las estrellas de acuerdo con la calificación
import 'package:flutter/material.dart';
import 'star.dart';
class DescriptionPlace extends StatelessWidget {
final String _namePlace;
final double _stars;
final String _descriptionPlace;
const DescriptionPlace(
this._namePlace,
this._stars,
this._descriptionPlace,
{super.key});
@override
Widget build(BuildContext context) {
final description = Container(
margin: const EdgeInsets.only(
top:20.0,
right: 20.0,
left: 20.0
),
child: Text(
_descriptionPlace,
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Color(0xFF56575a)
),
textAlign: TextAlign.left,
),
);
final titleStars = Row(
children: <Widget>[
Container(
margin: const EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0),
child: Text(
_namePlace,
style: const TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left
),
),
Row(
children: createStars(),
)
],
);
return Column(
children:<Widget>[
titleStars,
description
]);
}
List<Star> createStars(){
List<Star> stars = [];
if(_stars <= 5){
int numberStars = _stars.truncate();
int part = ((_stars * 10) % 10).toInt();
int remainStars = ( 5 - numberStars - (part > 0 ? 1 : 0));
for(int i=1;i<=numberStars;i++){
stars.add(const Star(Icons.star));
}
if(part > 0){
stars.add(const Star(Icons.star_half));
}
for(int i=1;i<=remainStars;i++){
stars.add(const Star(Icons.star_border));
}
return stars;
}
throw Exception('Number of stars is invalid');
}
}
Pensé un rato como podría simplificarse el código de ejemplo y llegué a esta conclusión.
Noté que, pensando que éste sea un componente reusable, no tiene mucho sentido escribir lógica de posicionamiento; también implementé una función para pintar correctamente las estrellas del rating basado en la puntuación que recibe el constructor.
Para que las estrellas aumenten o disminuyan me sirvio esto directamente, un poco sencillo ya que no evalua si es a la mitad.
Row(
children: [
for(var i = 0; i < stars; i++)
star,
],
Horrible si. Todo desactualizado. No se cuantos años tiene este curso. Mejor corto aca porque nada es igual. Ojala lo actualicen pronto.
Deberían hacerle una actualización a este curso mucha diferencia con el actual Flutter 3.3
Horrible en 2022, demasiado desactualizado el curso…
Me lanza un error cuando coloco solamente descriptionPlace, me toca poner this.descriptionPlace. ¿Algo cambió?
Adjunto mi propuesta actual de este ejercicio que tiene algunos cambios respecto la solución de la profesora:
import 'package:flutter/material.dart';
class DescriptionPlace extends StatefulWidget {
const DescriptionPlace({
Key? key,
required this.namePlace,
required this.descriptionPlace,
required this.stars,
}) : super(key: key);
final String namePlace;
final String descriptionPlace;
final int stars;
@override
State<DescriptionPlace> createState() => _DescriptionPlaceState();
}
class _DescriptionPlaceState extends State<DescriptionPlace> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: _buildRowWidgets(),
),
_buildDescription(),
],
);
}
List<Widget> _buildRowWidgets() {
List<Widget> rowList = [];
rowList.add(_buildTitle());
for (int i = 1; i <= 5; i++) {
rowList.add(_buildStar(i));
}
return rowList;
}
Container _buildTitle() {
return Container(
margin: const EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0,
),
child: Text(
widget.namePlace,
style: const TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900,
),
textAlign: TextAlign.left,
),
);
}
Container _buildDescription() {
return Container(
margin: const EdgeInsets.only(
top: 20.0,
left: 20.0,
right: 20.0,
),
child: Text(
widget.descriptionPlace,
style: const TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Color(0xFF56575A),
),
textAlign: TextAlign.left,
),
);
}
Container _buildStar(int order) {
return Container(
margin: const EdgeInsets.only(
top: 323.0,
right: 3.0,
),
child: Icon(
(order <= widget.stars) ? Icons.star : Icons.star_border,
color: const Color(0xFFf2C611),
),
);
}
}
¡Genial!! Cada día me gusta más este lenguaje de programación. ¡Siento que estoy aprendiendo un montón!
Busque otra forma interactiva de realizar las estrellas y encontre esta libreria que ya da hecho esta interaccion con las estrellas:
flutter_rating_bar: ^4.0.0
RatingBar.builder(
initialRating: 3,
minRating: 1,
direction: Axis.horizontal,
allowHalfRating: true,
itemCount: 5,
itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
itemBuilder: (context, _) => Icon(
Icons.star,
color: Colors.amber,
),
onRatingUpdate: (rating) {
print(rating);
},
);
cuando coloco String descriptionDummy = “texto”;
child: const Text(
descriptionDummy,
style: TextStyle(
fontFamily: ‘Raleway’, package: ‘my_package’,
fontSize: 16.0,
color: Color(0xFF56575a)
),
),
me da error no se que hacer…
Hice que se evaluara la calificación no importando el número que tenga la parte decimal de la calificación siempre y cuando la parte entera sea un numero entre 0 y 5.
Saludos, a continuación les dejo mi estilo para la solución de las estrellas. Utilizando un solo arreglo de widgets y un solo ciclo para llenar al arreglo una estrella, media estrella o estrella vacía según lo que corresponda.
List<Widget> starred = [];
for (var i = 0; i < 5; i++) {
if (i < stars) {
if((stars - i) == 0.5){
starred.add(starHalf);
}else{
starred.add(star);
}
} else {
starred.add(starBorder);
}
}
Posteriormente, mandamos ese arreglo al row
utilizando: children: starred
final titleStars = Row(
children: [
Container(
margin: EdgeInsets.only(top: 320.0, left: 20.0, right: 20.0),
child: Text(namePlace,
style: TextStyle(fontSize: 30.0, fontWeight: FontWeight.w900),
textAlign: TextAlign.left)),
Row(
children: starred,
)
],
);
yo lo hice de otra forma espero les sirva.
Pasar parametros a un widget
Listo, buena la practica de las estrellas
List<Widget> showStars() {
List<Widget> allStars = [];
for (int i = 1; i <= maxStars; i++) {
if ((stars.toInt()) >= i) {
allStars.add(star);
} else {
if (stars % 1 != 0 && ((stars.toInt()) + 1 ) == i) {
(stars % 1 >= 0.5)?allStars.add(star_half):allStars.add(star_border);
} else {
allStars.add(star_border);
}
}
}
return allStars;
}
final title_starts = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0
),
child: Text(
namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
),
),
Row(
children: showStars()
)
],
);
una forma rapida de crear un constructor desde android studio es presionar ctrl+enter y enter de nuevo para que te lo cree automaticamente con los atributos que ya creaste
Buenos días,
Les comparto mi reto:
![](
Hola a todos, yo cree esta función para asignar las estrellas
Widget buildStars(double puntuacion) {
int parteEntera = puntuacion.truncate();
List<Widget> rowStars = [];
for (int i = 0; i < parteEntera; i++) {
rowStars.add(star);
}
if (puntuacion > parteEntera) {
rowStars.add(starHalf);
}
if (rowStars.length < 5) {
for (int i = 0; i < 5 - rowStars.length; i++) {
rowStars.add(starBorder);
}
}
return new Row(children: rowStars);
}
import 'package:flutter/material.dart';
class DescriptionPlace extends StatelessWidget {
String namePlace;
int stars;
String descriptionPlace;
DescriptionPlace (this.namePlace, this.stars, this.descriptionPlace);
String context ="LAS WAIFUS SON CHICAS 2D QUE PUEDEN LOGRAR MAS COSAS QUE LAS 3D, NO LAS ABANDONES";
@override
Widget build(BuildContext context) {
// TODO: implement build
final Star = Container (
margin: EdgeInsets.only(
top: 233.0,
right: 3.0,
),
child: Icon(
Icons.star,
color: Colors.amber ,
),
);
final StarBorder = Container (
margin: EdgeInsets.only(
top: 233.0,
right: 3.0,
),
child: Icon(
Icons.star_border,
color: Colors.amber ,
),
);
final StarHalf = Container (
margin: EdgeInsets.only(
top: 233.0,
right: 3.0,
),
child: Icon(
Icons.star_half,
color: Colors.amber ,
),
);
final Context = Container(
margin: EdgeInsets.only(
top: 5.0,
left: 15.0,
right: 15.0,
),
child: Text (
descriptionPlace,
style: TextStyle (
fontSize: 16.0,
fontWeight: FontWeight.w300,
color: Colors.black
),
textAlign: TextAlign.left
),
);
final Stars = Row(
children: <Widget> [
Container(
margin: EdgeInsets.only(
top: 230.0,
left: 20.0,
right: 20.0,
) ,
child: Text (
namePlace,
style: TextStyle (
fontSize: 33.0,
fontWeight: FontWeight.w800
),
textAlign: TextAlign.left ,
),
),
Row(
children: <Widget> [
Star,
Star,
Star,
StarHalf,
StarBorder
],
)
],
);
return Column(
children: <Widget>[
Stars,
Context,
],
);
}
}```
Resolví mejor el planteamiento de los layout a mi gusto. De esta forma, solo cambias un solo margin y el resto se altera solo. Además quedó más adaptable al momento de cambiar a landscape desde el teléfono:
Además, abstraje de forma simple la puntuación de los lugares:
// Required imports
import 'package:flutter/material.dart';
class DescriptionPlace extends StatelessWidget {
// Variables
final String title;
final String description;
final int score;
// Constructor del Main Widget
DescriptionPlace(this.title, this.description, this.score);
// Star Widget
Widget starWidget(bool fulfilled) {
return Icon(
fulfilled ? Icons.star : Icons.star_border,
color: fulfilled ? Color(0xFFf0e21f) : Color(0xFFd6d6d6)
);
}
// Stars Widget Generator
List<Widget> generateStars() {
// Recursive generation
List<Widget> state = [];
for (int i = 0; i < 5; i++) {
state.add(
starWidget(i < score)
);
}
// Returning generated stars list
return state;
}
// Main Widget
@override
Widget build(BuildContext context) {
// Title Widget
final Container titleWidget = Container(
width: 210.0,
child: Text(
title,
textAlign: TextAlign.left,
style: TextStyle(
color: Color(0xFF212121),
fontSize: 29.0,
fontWeight: FontWeight.bold,
fontFamily: 'Montserrat'
)
)
);
// Stars Widget
final Container starsWidget = Container(
child: Row(
children: generateStars()
)
);
final Container descriptionWidget = Container(
margin: EdgeInsets.only(
top: 20.0
),
child: Text(
description,
textAlign: TextAlign.left,
style: TextStyle(
color: Color(0xFF212121),
fontSize: 17.0,
fontWeight: FontWeight.normal,
fontFamily: 'Nunito Sans'
)
)
);
// Widget
final Container widget = Container(
margin: EdgeInsets.only(
top: 320.0,
left: 25.0,
right: 25.0
),
child: Column(
children: [
Row(
children: <Widget> [
titleWidget,
starsWidget
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
descriptionWidget
]
)
);
// Return
return widget;
}
}```
Esta fue la implementación que hice para llenar las estrellas en función de una variable rating (que es double):
Widget getStar(IconData icon) {
return Container(
margin: EdgeInsets.only(top: 323.0, right: 3.0),
child: Icon(
icon,
color: Colors.amber,
size: 18.0,
),
);
}
List<Widget> getStars() {
var fullStars = rating.floor();
var hasHalf = rating != fullStars;
var offset = 5 - fullStars;
List<Widget> stars = List();
stars.addAll(List(fullStars)..fillRange(0, fullStars, getStar(Icons.star)));
if (hasHalf) {
stars.add(getStar(Icons.star_half));
stars.addAll(List(offset - 1)
..fillRange(0, offset - 1, getStar(Icons.star_border)));
} else {
stars.addAll(
List(offset)..fillRange(0, offset, getStar(Icons.star_border)));
}
return stars;
}
import ‘package:flutter/material.dart’;
class DesriptionPlace extends StatelessWidget {
int stars;
String namePlace;
String descriptionDummy =
“Lorem ipsum dolor sit amet consectetur adipiscing elit auctor, sapien leo praesent etiam iaculis metus ut, consequat lacinia taciti ultrices at tellus integer.\n \nNulla ad conubia donec senectus netus ultrices semper, metus malesuada ridiculus mollis varius himenaeos tellus, potenti habitasse natoque phasellus integer tristique”;
DesriptionPlace(this.namePlace, this.stars, );
@override
Widget build(BuildContext context) {
final star_half=Container(
margin: EdgeInsets.only(
top: 320.0,
right: 3.0,
),
child: Icon(
Icons.star_half,
color: Color(0xFFf2C611),
),
);
final star=Container(
margin: EdgeInsets.only(
top: 320.0,
right: 3.0,
),
child: Icon(
Icons.star,
color: Color(0xFFf2C611),
),
);
final star_border=Container(
margin: EdgeInsets.only(
top: 320.0,
right: 3.0,
),
child: Icon(
Icons.star_border,
color: Color(0xFFf2C611),
),
);
final tite_starts = Row(
children: [
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0,
),
child: Text(
namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900,
),
textAlign: TextAlign.center,
),
),
Row(
children: [
star,
star,
star,
star,
star_border
],
),
],
);
final descripcion_texto = Container(
margin: EdgeInsets.only(
top: 25.0,
left: 20,
),
child: Text(
descriptionDummy,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
),
),
);
return Column(
children: [
tite_starts,
descripcion_texto,
],
);
}
}
😄
Genial!
Widget _getStars(double total) {
if(total > 0) {
List<Widget> stars = [];
int limit = total.floor();
final star = Container(
margin: EdgeInsets.only(top: 23.0, right: 3.0),
child: Icon(Icons.star, color: Colors.yellow)
);
final star_half = Container(
margin: EdgeInsets.only(top: 23.0, right: 3.0),
child: Icon(Icons.star_half, color: Colors.yellow)
);
for(int i=0; i<limit; i++) {
stars.add(star);
}
if(total > limit) {
stars.add(star_half);
}
return Row(children: stars);
}
return null;
Genial!!
Revisando el código de @aragonesteban vi que se podian incluir las estrellas medio llenas.
Estaba trabajando en Flutter para iOS y cuando cambié para Android y quise modificar esa línea superior, me aparecieron varios errores que no puedo solucionar.
He buscando en internet acerca de cómo usar el IDE para Flutter y Android al mismo tiempo, pero no logro resolver el problema. Y ahora ya ni siquiera puedo compilar el proyecto.
Alguien puede ayudarme, por favor?
A partir del aporte de @mho, implementé un método que devuelve una fila de estrellas a partir de la variable “int stars” que pasamos como argumento al constructor de la clase DescriptionPlace.
El método se caracteriza por su simplicidad 😃
Les comparto mi forma de crear las estrellas dinámicas.
List<Widget> getStars(double stars){
List<Widget> starList = new List();
for(int i = 0;i<5;i++){
if(stars == 0){
starList.add(starBorder);
continue;
}
if((stars-1)>=0){
starList.add(star);
stars-=1;
continue;
}
if((stars-1)<0){
starList.add(starHalf);
stars = 0;
}
}
return starList;
}```
Cambié un poco el código para hacer una validación de estrellas que muestra la mitad, si los valores son decimales.
final String dataName;
final double dataStars;
final String dataDescription;
DescriptionPlace(this.dataName, this.dataStars, this.dataDescription);
Widget buildStar(int index){
return Container(
margin: EdgeInsets.only(
top: 2.0,
right: 3.0
),
child: Icon(
(index>=dataStars) ? Icons.star_border : (index>dataStars-1 && index<dataStars) ? Icons.star_half : Icons.star,
color: Colors.yellow,
)
);
}
//Row con las estrellas
Row(
children: List.generate(5, (index) => buildStar(index)),
),
Porque en algunas lineas de codigo se finaliza con una coma, y en otras no?
Por ejemplo, al hacer el return Column, “title_stars” tiene coma pero “description” no. Gracias
Dejo mi implementación de las estrellas teniendo en cuenta que puede haber decimales.
Widget getItemWithIcon(IconData icon) => Container(
child: Icon(
icon,
color: Colors.yellowAccent,
),
margin: EdgeInsets.only(top:243),
);
List<Widget> getStarsComponent(double rank) {
List<Widget> starStack = [];
for (int i = 1; i <= 5; i++) {
if (i <= rank){
starStack.add(getItemWithIcon(Icons.star));
}
else if (rank%rank.round()!=0){
starStack.add(getItemWithIcon(Icons.star_half));
break;
}
}
if(starStack.length < 5) {
int starsList = starStack.length;
for (;starsList < 5; starsList++) {
starStack.add(getItemWithIcon(Icons.star_border));
}
}
return starStack;
}
Mi solución para tener las estrellas dinamicas segun el número(puede ser decimal) pasado por parametro.
La idea del return de esa forma la tome del aporte de uno de los compañeros
Widget GetStarts(double numStars){
List<Widget> rowStars = [];
int qStars = numStars.round();
for(var i = 1; i <= 5; i++){
if(i < qStars){
rowStars.add(starFull);
} else if(i > qStars){
rowStars.add(starEmpty);
} else{
if(numStars % 1 == 0){
//Es entero
rowStars.add(starFull);
}else{
rowStars.add(starHalf);
}
}
}
return Row(
children: rowStars
);
}
Solución de las dinámicas en 4 lineas
for (var i = 0; i < 5; i++)
if(i<this.stars.toInt())star,
if(this.stars.round()>this.stars.toInt())half_star,
for(var i=0;i<(5-this.stars.round());i++)empty_star,```
Hice lo de las estrellas:
Widget starAmount(dynamic number) {
List<Widget> stars = List();
for (int i = 1; i <= number; i++) {
stars.add(star);
}
bool uno = number is double;
print("El numero de las estrellas es double? $uno");
var starLength = stars.length;
if (number is double) {
stars.add(half_star);
if (number < 4) {
switch (starLength) {
case 3:
stars.add(border_star);
break;
case 2:
stars.add(border_star);
stars.add(border_star);
break;
}
}
return Row(
children: stars,
);
}
if (stars.length < 5) {
switch (starLength) {
case 4:
stars.add(border_star);
break;
case 3:
stars.add(border_star);
stars.add(border_star);
break;
case 2:
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
break;
case 3:
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
break;
case 1:
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
break;
case 0:
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
stars.add(border_star);
break;
}
}
return Row(
children: stars,
);
}
Y aqui esta el Row de titleStars:
Row(
children: <Widget>[
starAmount(stars),
],
),
para hacer mas facil la esrtrelals se puede usar
Row(
children: List.generate(5, (x) => start),
),
Saludos, mi forma de hacer las estrellas dinámicas, falta validar el número de estrellas en el constructor que no pasen de cinco o negativos.
var starsf = List.generate(stars, (x) => star);
starsf.addAll(List.generate(5 - stars, (x) => starBorder));
.
.
.
Row(
children: starsf,
),
La variable Int starts
luego se crea el constructor pero luego al pasarle los parametros “bahamas”, “descripcion del lugar” pero al poner la cantidad de estrellas que quiero que se muestren en pantalla no aparece colo 4 como tal lo dice la profe pero luego cambio y sigo viendo lo mismo alguien me puede explicar el porque ?
Agregando el half_star en cuando el decimal es igual o mayo a .5, en mi codigo el numero de estrellas es un double.
List<Widget> _setStars() {
List<Widget> list = new List<Widget>();
int stars = _numStars.floor();
bool addhalfStar = ((_numStars - stars) > .4);
list = List.generate(stars, (s) => star);
if (addhalfStar) {
list.add(halfStar);
stars++;
}
list.addAll(List.generate((5 - stars), (s) => voidStar));
return list;
}
}```
Con esto pueden renderizar el numero de estrellas que le pasen
for(var i=0; i<starts; i+=1) start
Que diferencia hay en poner margin: EdgeInsets.only y margin:new EdgeInsets.only?
Vi las soluciones, yo la plantee usando modulo y la división exacta.
List<Widget> list_star=new List<Widget>();
int num=starts~/1;
double num_half=starts%1;
int flag=0;//usaremos este flag solo una vez
for(int i =1;i<=5;i++)
{
if(num_half==0)//si no hay residuo
{
if(i<=num)
list_star.add(star);
if(i>num)
list_star.add(strella_vacia);
}
else//si hay residuo
{
if(i<=num)
list_star.add(star);
}
if(i>num && flag==1){
list_star.add(strella_vacia);
}
if(i>num && flag==0){
list_star.add(strella_semi);
flag=1;
}
}```
Les dejo mi solución para el calculo de las estrellas. No está muy probado pero creo que funciona bien jaja
List<Widget> calculateStarList() {
int starTruncated = stars.truncate();
int starFilled = starTruncated;
double decimal = stars % starTruncated;
bool starHalf = decimal > 0.1 && decimal < 0.9;
if (decimal >= 0.9) {
starFilled++;
}
return List.generate(5, (index) {
if(starFilled >0) {
starFilled--;
return star;
}
if(starHalf) {
starHalf = false;
return star_half;
}
return star_border;
});
}```
Hasta ahora todo bien, me gusta la forma de programar en Flutter.
Genial! 😃
Es interesante ver que a todo mundo le incomodo el que no se utilizara la variables int stars; y se pusieron a resolverlo. Clap!
Hola a todos, quisiera una asesoría ; debo hacer un proyecto con una app movil la cual va a contar con servidores en la nube( escalabilidad, alta disponibilidad y pago por uso).
No se en que lenguaje implementarla para posteriormente conectar la app con la nube
Tengo este error, favor si me pueden ayudar:
Esta es mi aproximación para poder usar estrellas generadas de manera dinámica en la app:
Widget setStars(double nStarts) {
int not_empty = 0;
List<Widget> starsToShow = List<Widget>();
while(nStarts >= 1) {
starsToShow.add(star);
nStarts--;
not_empty++;
}
while(nStarts > 0) {
starsToShow.add(star_half);
nStarts -= 0.5;
not_empty++;
}
for(int i = 0;i < 5 - not_empty;i++){
starsToShow.add(star_border);
}
return Row(children:starsToShow);
}
Después solo deben llamar a la función de la siguiente manera:
final title_stars = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320,
left: 20.0,
right: 20.0
),
child: Text(
namePlace,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900
),
textAlign: TextAlign.left,
),
),
setStars(stars)
],
);
Para hacer el rating mas dinamico:
final fullStar = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0,
),
child: Icon(
Icons.star,
color: Color(0xFFF2C611),
),
);
final halfStar = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0,
),
child: Icon(
Icons.star_half,
color: Color(0xFFF2C611),
),
);
final emptyStar = Container(
margin: EdgeInsets.only(
top: 323.0,
right: 3.0,
),
child: Icon(
Icons.star_border,
color: Color(0xFFF2C611),
),
);
var rating = <Widget>[];
for (int i = 1; i <= 5; i++) {
if (i <= stars) {
rating.add(fullStar);
} else if (stars - i == -0.5) {
rating.add(halfStar);
} else {
rating.add(emptyStar);
}
}
// ...
final starsTitle = Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
top: 320.0,
left: 20.0,
right: 20.0,
),
child: Text(
placeName,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w900,
),
textAlign: TextAlign.left,
)),
Row(
children: rating,
)
],
);
En flutter el “this” funciona igual que javascript?
Ojo, los archivos de la clase ya no están disponibles!
Quiero subir mi imagen, pero no me deja cuando arrastro el screen shot :c
Comparto una forma de colocar dinámicamente las estrellas
Widget showStars(double numStars) {
List<Widget> starsToShow = [];
List(numStars.truncate()).forEach((i) => starsToShow.add(star(1)));
if (numStars.remainder(numStars.truncate()).ceil() >= 1) {
numStars++;
}
List(numStars.remainder(numStars.truncate()).ceil())
.forEach((i) => starsToShow.add(star(2)));
List((numStars.truncate() - 5).abs())
.forEach((i) => starsToShow.add(star(3)));
return Row(
children: starsToShow,
);
}
Widget star(int type) {
return Container(
margin: EdgeInsets.only(top: 303.0, right: 3.0),
child: Icon(
type == 1
? Icons.star
: type == 2
? Icons.star_half
: Icons.star_border,
color: Color(0xFFf2c611)));
}
Alguien aquí ya quizo hacer lo de las estrellas más dinámico, aquí les dejo otra solución para ello:
Definimos un método que genere las estrellas de forma dinámica:
Widget generateStarIcon(IconData icon) => Container(
margin: EdgeInsets.only(right: 3),
child: Icon(
icon,
color: Color(0xFFf2C611),
),
);
Y después usamos ese método para construirlas en el build:
final halfStar = generateStarIcon(Icons.star_half);
final star = generateStarIcon(Icons.star);
final emptyStar = generateStarIcon(Icons.star_outline);
Yo lo implementé de esta forma:
final description = Column(
children: [
Container(
margin: EdgeInsets.only(
top: 25.0,
left: 20.0,
right: 20.0,
),
child: Text(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.left,
),
),
Container(
margin: EdgeInsets.only(
top: 20.0,
left: 20.0,
right: 20.0,
),
child: Text(
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architect",
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.left,
),
),
],
);
return Column(
children: [
title_stars,
description,
],
);```
Aquí el resultado:
![Screenshot 2021-02-15 124214.png](https://static.platzi.com/media/user_upload/Screenshot%202021-02-15%20124214-cb4599f1-fb65-4b69-92e3-8a762c63271a.jpg)
Lo implemente en una clase aparte
import 'package:flutter/material.dart';
typedef void RatingChangeCallback(double rating);
class StarRating extends StatelessWidget {
final int starCount;
final double rating;
final RatingChangeCallback onRatingChanged;
final Color color;
StarRating(
{this.starCount = 5, this.rating = .0, this.onRatingChanged, this.color});
Widget buildStar(BuildContext context, int index) {
Icon icon;
if (index >= rating) {
icon = new Icon(
Icons.star_border,
color: Theme.of(context).buttonColor,
);
} else if (index > rating - 1 && index < rating) {
icon = new Icon(
Icons.star_half,
color: color ?? Theme.of(context).primaryColor,
);
} else {
icon = new Icon(
Icons.star,
color: color ?? Theme.of(context).primaryColor,
);
}
return new InkResponse(
onTap:
onRatingChanged == null ? null : () => onRatingChanged(index + 1.0),
child: icon,
);
}
@override
Widget build(BuildContext context) {
return new Row(
children:
new List.generate(starCount, (index) => buildStar(context, index)));
}
}
Hice un pequeño Widget para abstraer toda la funcionalidad de un rating de estrellas que se podría ir mejorando.
import 'package:flutter/material.dart';
class StarsRating extends StatelessWidget {
final int rating;
StarsRating(this.rating);
Widget ratingStar(bool fill) {
return Container(
margin: EdgeInsets.only(top: 323, right: 3),
child: Icon(
fill ? Icons.star : Icons.star_border,
color: Colors.amber,
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> stars = [];
List(rating).forEach((i) => stars.add(ratingStar(true)));
List((rating - 5).abs()).forEach((i) => stars.add(ratingStar(false)));
return Row(children: stars);
}
}
Al final el widget sólo se usaría así donde sea necesario:
final title = Row(
children: [
Container(
margin: EdgeInsets.only(
top: 320,
left: 20,
right: 20,
),
child: Text(
name,
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w900,
),
textAlign: TextAlign.left,
),
),
StarsRating(rate),
],
);
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?