Bienvenida e Introducción

1

¡Renovaremos este curso!

2

Desarrollando en Flutter

3

¿Qué es Flutter?

4

Dart y Flutter

5

Sintaxis de Dart

6

¡Renovaremos este curso!

7

Flutter para desarrolladores Android, iOS y Xamarin.forms

8

Flutter para desarrolladores React Native

9

¿Cómo luce una app construída en Flutter?

10

Primer reto

Creando mi entorno de desarrollo

11

¡Renovaremos este curso!

12

Requerimientos de Hardware y Software

13

Instalando Flutter en Android Studio y Visual Studio Code

14

Composición de un proyecto en Flutter

Interfaces en Flutter

15

¡Renovaremos este curso! Te quedan unos días para concluirlo.

16

Programación Declarativa en Flutter

17

Estructura de un programa en Flutter

18

Hola Mundo en Flutter

19

Widgets básicos

20

Widgets con estado y sin estado

21

Análisis de Interfaces de Usuario en Flutter

22

Definiendo los layouts de nuestra interfaz

23

Segundo reto

Widgets sin estado en Flutter

24

¡Renovaremos este curso! Te quedan unos días para concluirlo.

25

Flutter Widgets: Container, Text, Icon, Row

26

Flutter Widgets: Column

27

Recursos en Flutter: Tipografías y Google Fonts

28

Widget Image

29

Widget Apilando Textos

30

Widgets Decorados

31

Widget Imagen Decorada

32

Widget Listview

33

Widget Button, InkWell

34

Tercer reto

Widgets con estado en Flutter

35

¡Renovaremos este curso! Te quedan unos días para concluirlo.

36

Botones en Flutter

37

Clase StatefulWidget: Cómo se compone

38

Widget Floating Action Button

39

Widgets BottomNavigationBar

40

Generando Navegación en BottomNavigationBar

41

Personalizando nuestro BottomNavigation Bar a Cupertino iOS BottomBar

42

Cuarto reto

Fin del Curso

43

¡Renovaremos este curso!

44

Conclusiones

45

¡Terminamos!

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Flutter

Curso de Flutter

Anahí Salgado Díaz de la Vega

Anahí Salgado Díaz de la Vega

Flutter Widgets: Column

26/45
Recursos

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

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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),
      ],
    );