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

Widget Apilando Textos

29/45
Recursos

Cuando hablamos de apilar textos nos referimos a organizarlos de tal forma que queden unos arriba de otros formando items compuestos que luego serán parte de una lista. Para esto nos apoyaremos en los widgets: Container(), Text() y Column(), dispuestos convenientemente en un widget tree que en próximas clases completaremos con la funcionalidad de scrolling como ya veremos.

Siguiendo el análisis de la interfaz de nuestro proyecto, que hicimos en clases anteriores, haremos la composición de nuestro widget review, y luego del widget reviewList.

Presta especial atención al uso de los widgets Text y TextStyle, ya que son claves para definir la apariencia de los textos en la lista de reviews.

Progresivamente iremos apilante los textos que vamos definiendo de forma individual, usando el widget Column(), que como ya hemos visto en clases anteriores, nos permite organizar los widgets hijos unos arriba de los otros en el eje Y.

Aportes 71

Preguntas 11

Ordenar por:

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


Cree la Rating para generar las estrellas y reutilizarla en la descripción y en los reviews.

rating.dart

import 'package:flutter/material.dart';

class Rating extends StatelessWidget {
  double stars;
  double marginLeft;
  double fontSize;

  Rating(this.stars, this.marginLeft, this.fontSize);

  Widget getStar(double star) {
    var icon = Icons.star;

    if (star == 0.5) {
      icon = Icons.star_half;
    } else if (star < 0.5) {
      icon = Icons.star_border;
    }
    return Container(
      margin: EdgeInsets.only(right: 3.0),
      child: Icon(
        icon,
        color: Color(0xFFf2C611),
        size: fontSize,
      ),
    );
  }

  Widget getRating(double stars) {
    var list = new List<Widget>();

    for (var n = 0; n < 5; n++) {
      list.add(getStar(stars));
      stars--;
    }
    return Container(
      margin: EdgeInsets.only(left: marginLeft),
      child: Row(
        children: list,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return getRating(stars);
  }
}

Utilicé la clase Rating en la clase de Review para generar las estrellas.

review.dart

import 'package:flutter/material.dart';
import 'rating.dart';

class Review extends StatelessWidget {
  String pathImage = 'assets/img/frank.jpeg';
  String name = 'Francisco Peñalo';
  String details = '1 review 5 photos';
  double stars = 5;
  String comment = 'There is an amazing place in ';

  Review(this.pathImage, this.name, this.details, this.stars, this.comment);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    final userComment = Container(
      margin: EdgeInsets.only(left: 20.0),
      child: Text(comment,
          textAlign: TextAlign.left,
          style: TextStyle(
            fontFamily: 'Lato',
            fontSize: 13.0,
            fontWeight: FontWeight.w900,
          )),
    );

    final userInfo = Row(
      children: <Widget>[
        Container(
          margin: EdgeInsets.only(left: 20.0),
          child: Text(details,
              textAlign: TextAlign.left,
              style: TextStyle(
                fontFamily: 'Lato',
                fontSize: 13.0,
                color: Color(0xFFa3a5a7),
              )),
        ),
        Rating(stars, 5.0, 14.0)
      ],
    );

    final userName = Container(
      margin: EdgeInsets.only(
        left: 20.0,
      ),
      child: Text(name,
          textAlign: TextAlign.left,
          style: TextStyle(
            fontFamily: 'Lato',
            fontSize: 17.0,
          )),
    );

    final userDetails = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        userName,
        userInfo,
        userComment,
      ],
    );

    final photo = Container(
      margin: EdgeInsets.only(top: 20.0, left: 20.0),
      width: 80.0,
      height: 80.0,
      decoration: BoxDecoration(
          shape: BoxShape.circle,
          image: DecorationImage(
            fit: BoxFit.cover,
            image: AssetImage(pathImage),
          )),
    );

    return Row(
      children: <Widget>[
        photo,
        userDetails,
      ],
    );
  }
}

Listo, tuve el inconveniente que al querer agregar varios reviews, me salia una franja con líneas negras y amarillas que es porque me estaba pasando del limite de espacio a que en el main agrege un widget SingleChildScrollView, con el cual ya podia desplazarme para poder ver todos los reviews.

este curso no es para nada basico!.
y segun platzi este es lo mas basico que pueden hacer. no me jodan si hasta parece apurada la docente

Para los que están probando en dispositivos de menor resolución y su texto de comentario es personalizado y genera error por sobrepasar el ancho, usen el widget Flexible:

final userDetails = Flexible(
        child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          userName,
          userInfo,
          userComment
        ],
      ),
    );

Resultado:

Esta fue mi solución para manejar las estrellas con decimales.

Reto cumplido pero le añadí algunas funciones. Bueno separe la lógica de las estrellas en una clase para reutilizarlas en cualquier lugar. Ciertas partes son código de otros estudiantes y logre al final hacer esto.

import 'package:flutter/material.dart';

class Star extends StatelessWidget {

  // Numeros por default
  final int _defaultNumberStar = 5;
  final double _defaultStarSize = 14.0;
  final Color _defaultStarColor = const Color(0xFFF2C611);

  final int stars;

  final Color color;

  final double starSize;

  final EdgeInsets margin;

  // Esto lo utilizo como limitador de la cantidad de estrellas
  final int numberStar;

  const Star(this.stars, {
    this.color,
    this.starSize,
    this.margin,
    this.numberStar
  });

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return showStars(stars);
  }

  Widget star(bool withBorder) {
    return Container(
      margin: margin,
      child: Icon(
          withBorder ? Icons.star : Icons.star_border,
          size: starSize ?? _defaultStarSize,
          color: color ?? _defaultStarColor
      ),
    );
  }

  Widget showStars(int numberStars) {
    List<Widget> rowStars = [];
    List<Widget> rowStarsBorder = [];
    List(numberStars).forEach((i) => rowStars.add(star(true)));

   // muy importante porner el parentisis de lo contrario les saldra error
   // a (numberStar ?? _defaultNumberStar)
    List((numberStars - (numberStar ?? _defaultNumberStar)).abs())
        .forEach((i) => rowStarsBorder.add(star(false)));
    List<Widget> finalStar = []..addAll(rowStars)..addAll(rowStarsBorder);
    return Row(children: finalStar);
  }

}

Ahora para implementarlo solo hacemos esto.

  final userInfo = Row(
      children: <Widget>[
        Container(
          margin: EdgeInsets.only(
            left: 20.0,
          ),

          child: Text(
            details,
            textAlign: TextAlign.left,
            style: TextStyle(
              fontFamily: "Lato",
              fontSize: 13.0,
              color: Color(0xFFa3a5a7)
            ),
          ),
        ),
        // Le paso un numero de estrellas, ademas le indico que tamaño quiero 
       // que tenga y algunos margins.
        Star(stars,
            starSize: 11.0,
            margin: EdgeInsets.only(
                right: 3.0
            ))
      ],
    );

Bueno no soy un experto solo mire como estaban construidas algunas clases internas y se me ocurrió hacer esto.

Que lo disfruten.

Termine!

class ReviewList extends StatelessWidget {
  List<String> names = ["Kevin Melendez", "Vivis Garcia", "Liliana Mondragon", "Aron Diaz"];
  List<String> comment = ["Me parece un lugar lleno de gente calida y amable, el interior de su iglesia es increíble.",
  "Agradable, lo unico que lamento es no haber ido a piedra labrada.",
  "Me agrado conocer esta ciudad recorrerla junto a mi pareja fue lo mejor, sin duda volveria a este lugar.",
  "Al principio tenia dudas del lugar y aunque no me gusto el clima, la ciudad es hermosa"];
  List<double> stars = [3.5, 3, 4, 5];
   @override
  Widget build(BuildContext context) {
    return Column(
      children: List.generate(3, (x)=>  Review("assets/img/user$x.jpg", names[x], 2, 4, comment[x], stars[x])),
    );
  }
}

Lo hice pero me bota una franja amarilla abajo Bottom Overloaded

Curso avanzado de Flutter para integrar código nativo de Kotlin y Swift

¡Vamos por buen camino! Logré hacer dinámico las estrellas también :3

Listo!

Aqui esta la clase ReviewList:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:super_trips_app/review.dart';
import 'package:super_trips_app/description.dart';

class ReviewList extends StatelessWidget {

  List<Review> lista = List<Review>();
  String title;
  String desc;
  dynamic stars;

  ReviewList(this.lista, this.title, this.desc, this.stars);

  @override
  Widget build(BuildContext context) {

    return Column(

        children: <Widget>[

          Description(title, stars, desc, 30.0),
          getWidgets(lista),

        ]

    );

  }

  Column getWidgets(List list1)
  {
    List<Review> list = new List<Review>();

    for(int i = 0; i < list1.length; i++){

      list.add(list1[i]);

    }
    return Column(
        children: list
    );
  }

}

y el Scaffold de Home:

home: Scaffold(

          appBar: AppBar(

            title: Text("Hola Mundo!"),

          ),
          body: ReviewList(reviewsAdd(), "Duwili Ella", "Lorem Ipsum is a simply dummy text\nof the printing and typesetting industry", 3.5),

      ),
    );

Reto:

Mi solución:

/**Clase ReviewList**/
import 'package:flutter/material.dart';
class ReviewList extends StatelessWidget{
  List<Widget> items = [];
  ReviewList(this.items);
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    final reviewList = Column(
      children: items
    );
    return reviewList;
  }
}

/**Clase Review**/
import 'package:flutter/material.dart';
import 'review_stars.dart';
class Review extends StatelessWidget{
  String pathImage = 'assets/images/profile.jpg';
  String name = "Varuna Yasas";
  String details = "1 review 5 photos";
  String comment = "There is an amazing place in Sri Lanka";
  num    numStars = 0;
  Review(this.pathImage, this.name, this.details, this.comment, this.numStars);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    final userName = Container(
      margin: EdgeInsets.only(
        left: 20.0,
        bottom: 5.0
      ),
      child: Text(
        name,
        textAlign: TextAlign.left,
        style:TextStyle(
          fontSize: 17.0,
          fontFamily: "Lato"
        )
      ),
    );

    final userReview = Container(
      margin: EdgeInsets.only(
        left: 20.0,
        bottom: 5.0,
      ),
      child: Text(
          details,
          textAlign: TextAlign.left,
          style:TextStyle(
              fontSize: 13.0,
              fontFamily: "Lato",
              color:Color(0xFFA3A5A7)
          )
      ),
    );

    final userInfo = Row(
      children: <Widget>[
        userReview,
        Container(
          margin: EdgeInsets.only(
            left: 10.0
          ),
          child: new ReviewStars(numStars,13.0),
        )
      ],
    );

    final userComment = Container(
      margin: EdgeInsets.only(
          left: 20.0
      ),
      child: Text(
          comment,
          textAlign: TextAlign.left,
          style:TextStyle(
              fontSize: 13.0,
              fontFamily: "Lato",
              fontWeight: FontWeight.w500
          )
      ),
    );

    final userDetails = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        userName,
        userInfo,
        userComment
      ],
    );


    final photo = Container(
      margin: EdgeInsets.only(
        top: 20.0,
        left: 20.0
      ),
      width: 80.0,
      height: 80.0,

      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
          fit: BoxFit.cover,
          image: AssetImage(pathImage)
        )
      ),
    );

    final items = Row(
      children: <Widget>[
        photo,
        userDetails
      ],
    );
    return items;
  }

}

/**Clase ReviewStars**/
import 'package:flutter/material.dart';
class ReviewStars extends StatelessWidget{
  num numStars = 0;
  num iconSize = 24;
  ReviewStars(this.numStars, this.iconSize);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    final List<Widget> starsList = [];
    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(
          right: 3.0
      ),
      child: Icon(
        Icons.star_border,
        color: Color(0xFFF2C716),
        size: iconSize,
      ),
    );

    final star_half = Container(
      margin: EdgeInsets.only(
          right: 3.0
      ),
      child: Icon(
        Icons.star_half,
        color: Color(0xFFF2C716),
        size: iconSize
      ),
    );

    final star = Container(
      margin: EdgeInsets.only(
          right: 3.0
      ),
      child: Icon(
        Icons.star,
        color: Color(0xFFF2C716),
        size: iconSize
      ),
    );

    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 _reviewStars = Row(
      children: starsList,
    );
    return _reviewStars;
  }
}

/**Clase DescriptionPlace**/
import 'package:flutter/material.dart';
import 'review_stars.dart';
import 'review.dart';
import 'review_list.dart';

class DescriptionPlace extends StatelessWidget {
  String namePlace;
  String descriptionPlace;
  num    numStars;
  List<Widget> reviewList = [];

  DescriptionPlace(this.namePlace, this.descriptionPlace, this.numStars);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    final title_stars = Row(
      children: <Widget>[
        Container(
          margin: EdgeInsets.only(
            top: 300.0,
            left: 20.0,
            right: 20.0
          ),
          child: Text(
            namePlace,
            style: TextStyle(
              //fontFamily: "Lato",
              fontSize: 30.0,
              fontWeight: FontWeight.w900
            ),
            textAlign: TextAlign.left,
          ),
        ),
        Container(
          margin: EdgeInsets.only(
            top:303.0
          ),
          child: new ReviewStars(numStars,24.0),
        )
      ],
    );

    final descripction_text = Container(
      margin: EdgeInsets.only(
        top: 10.0,
        left: 20.0,
        right: 20.0,
        bottom: 5.0
      ),
      child: Text(
        descriptionPlace,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 12.0,
          color: Color(0xFF6D6E71)
        ),
        textAlign: TextAlign.justify,

      )
    );


    for(var i = 0; i<2;i++){
      reviewList.add(new Review('assets/images/profile.jpg',"Varuna Yasas","1 review 5 photos","There is an amazing place in Sri Lanka", numStars));
    }


    final _description_place = Column(
      children: <Widget>[
        title_stars,
        descripction_text,
        new ReviewList(reviewList)
      ],
    );

    return _description_place;
  }

}


Review list

class ReviewList extends StatelessWidget{

  String pathImage = "assets/img/people.jpg";
  String name = "Varuma Yasas";
  String details = "1 rewiew 5 photos";
  String comment = "There is an amazing place in Sri Lanka";

  ReviewList();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      children: <Widget>[
        Review(pathImage, name, details, comment),
        Review(pathImage, name, details, comment)
      ],
    );
  }

}

Review

class Review extends StatelessWidget{

  String pathImage;// = "assets/img/people.jpg";
  String name;// = "Varuma Yasas";
  String details;// = "1 rewiew 5 photos";
  String comment;// = "There is an amazing place in Sri Lanka";

  Review(this.pathImage, this.name, this.details, this.comment);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    final star_half = Container(
      margin: EdgeInsets.only(
          top: 3.0,
          right: 3.0
      ),
      child: Icon(
        Icons.star_half,
        size: 11.0,
        color: Color(0xFFf2C611),
      ),
    );

    final star_border = Container(
      margin: EdgeInsets.only(
          top: 3.0,
          right: 3.0
      ),
      child: Icon(
        Icons.star_border,
        size: 11.0,
        color: Color(0xFFf2C611),
      ),
    );

    final star = Container(
      margin: EdgeInsets.only(
          top: 3.0,
          right: 3.0
      ),
      child: Icon(
        Icons.star,
        size: 11.0,
        color: Color(0xFFf2C611),
      ),
    );

    final userComment = Container(
      margin: EdgeInsets.only(
          left: 20.0
      ),

      child: Text(
        comment ,
        textAlign: TextAlign.left,
        style: TextStyle(
            fontFamily: "Lato",
            fontSize: 13.0,
            fontWeight: FontWeight.w900

        ),
      ),
    );


    final userInfo = Row(
      children: <Widget>[
        Container(
          margin: EdgeInsets.only(
              left: 20.0,
            right: 10.0
          ),
          child: Text(
            details,
            textAlign: TextAlign.left,
            style: TextStyle(
                fontFamily: "Lato",
                fontSize: 13.0,
                color: Color(0xFFa3a5a7)
            ),
          ),
        ),
        Row(
          children: <Widget>[
            star,
            star,
            star,
            star_half,
            star_border
          ],
        )
      ],
    );

    final userName = Container(
      margin: EdgeInsets.only(
        left: 20.0
      ),

      child: Text(
        name,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 17.0
        ),

      ),

    );

    final userDetails = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        userName,
        userInfo,
        userComment

      ],
    );

    final photo = Container(
      margin: EdgeInsets.only(
        top: 20.0,
        left: 20.0
      ),
      width: 80.0,
      height: 80.0,

      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
            fit: BoxFit.cover,
            image: AssetImage(pathImage))
      ),
    );

    return Row(
      children: <Widget>[
        photo,
        userDetails
      ],
    );
  }

Description place

final description_place = Column(
      children: <Widget>[
        title_starts,
        description,
        new ReviewList()
      ],
    );

Listo!

import ‘package:flutter/cupertino.dart’;
import ‘package:flutter/material.dart’;

// ignore: must_be_immutable
class Review extends StatelessWidget{

String pathImage =“Sintítulo.png”;
String name = “Esteban Eguiguren”;
String details = “1 review 5 photos”;
String comment = “excelente”;

Review(this.pathImage,this.name,this.details,this.comment);
@override
Widget build(BuildContext context) {
// TODO: implement build

final userComment = Container(
  margin: EdgeInsets.only(
      left: 20.0
  ),
  child: Text(
    comment,
    textAlign: TextAlign.left,
    style: TextStyle(
        fontSize: 13.0,
        fontFamily: "Lato",
        fontWeight: FontWeight.w900
    ),
  ),
);

final userInfo= Container(
  margin: EdgeInsets.only(
      left: 20.0
  ),
  child: Text(
    details,
    textAlign: TextAlign.left,
    style: TextStyle(
        fontSize: 13.0,
        fontFamily: "Lato",
      color: Color(0xFFa3a5a7)
    ),
  ),
);

final userName = Container(
  margin: EdgeInsets.only(
    left: 20.0
  ),
      child: Text(
        name,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontSize: 17.0,
          fontFamily: "Lato"
        ),
),
);


final photo= Container(
  margin: EdgeInsets.only(
    top:20.0,
    left: 20.0,
  ),

  width: 80.0,
  height: 80.0,

  decoration: BoxDecoration(
      shape:  BoxShape.circle,
      image: DecorationImage(
          fit: BoxFit.cover,
          image:NetworkImage(pathImage)),
          //AssetImage(pathImage))
  )
);

final star=Container(
  margin: EdgeInsets.only(
    left: 15.0,
    right: 1.0
  ),
  child: Icon(
    Icons.star,
    color: Color(0xFFF2C611),
  ),
  width: 1.0,
);

  final userDetails = Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: <Widget>[
    userName,
    Row(
      children: <Widget>[
        userInfo,
        star,
        star,
        star,
        star,
        star
      ],
    ),

    userComment,
  ],
);

return Row(
  children: <Widget>[
    photo,
    userDetails

  ],
);

}

}

clase para las estrellas incluidos rangos medios como 3.5

import 'package:flutter/material.dart';

class Rating extends StatelessWidget {
  const Rating({required this.stars, super.key});

  final double stars;

  @override
  Widget build(BuildContext context) {

    final star = Container(
      child: const Icon(
        Icons.star,
        color: Color(0xFFf2C611),
      ),
    );

    final star_half = Container(
      child: const Icon(
        Icons.star_half,
        color: Color(0xFFf2C611),
      ),
    );

    final star_border = Container(
      child: const Icon(
        Icons.star_border,
        color: Color(0xFFf2C611),
      ),
    );

    
    double borderStar = 5.0 - stars;
    List <String> rank = stars.toString().split('.');
    List <Widget> rankList = [];

    for (int i = 0; i <= int.parse(rank[0]); i++) {
      rankList.add(star);
    }

    if (rank.length > 1) {
      if (rank[1] == '5') rankList.add(star_half);
    }

    if (borderStar > 0) {
      for (int i = 0; i < int.parse(borderStar.toString().split('.')[0]); i++) {
        rankList.add(star_border);
      }
    }

    return Row(
      children: rankList
    );
  }
}

He creado la clase starts_util.dart que genera un Row de estrellas dependiendo del avg rating de una lista de ratings:

import 'package:flutter/material.dart';

class StartsUtil extends StatelessWidget {

  List<int> ratingList = [5, 4, 3, 4];

  StartsUtil(this.ratingList);

  @override
  Widget build(BuildContext context) {

    var ratingSum = ratingList.reduce((value, element) => value + element);
    var ratingAvg = ratingSum / ratingList.length;

    final startHalf = _createStart(Icons.star_half);
    final startEmpty = _createStart(Icons.star_outline);
    final start = _createStart(Icons.star);

    late final Row startsRow;

    if(ratingAvg == 0.0) {
      startsRow = Row(
        children: [
          startEmpty,
          startEmpty,
          startEmpty,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 0.5) {
      startsRow = Row(
        children: [
          startHalf,
          startEmpty,
          startEmpty,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 1) {
      startsRow = Row(
        children: [
          start,
          startEmpty,
          startEmpty,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 1.5) {
      startsRow = Row(
        children: [
          start,
          startHalf,
          startEmpty,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 2) {
      startsRow = Row(
        children: [
          start,
          start,
          startEmpty,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 2.5) {
      startsRow = Row(
        children: [
          start,
          start,
          startHalf,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 3) {
      startsRow = Row(
        children: [
          start,
          start,
          start,
          startEmpty,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 3.5) {
      startsRow = Row(
        children: [
          start,
          start,
          start,
          startHalf,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 4) {
      startsRow = Row(
        children: [
          start,
          start,
          start,
          start,
          startEmpty
        ],
      );
    } else if(ratingAvg <= 4.5) {
      startsRow = Row(
        children: [
          start,
          start,
          start,
          start,
          startHalf
        ],
      );
    } else if(ratingAvg <= 5) {
      startsRow = Row(
        children: [
          start,
          start,
          start,
          start,
          start
        ],
      );
    }

    return startsRow;
  }

  Container _createStart(IconData startType) {
    final start = Container(
      margin: const EdgeInsets.only(top: 323.0, right: 3.0),
      child: Icon(
        startType,
        color: const Color(0xFFf2C611),
      ),
    );
    return start;
  }
}

Les dejo mi aporte a esta clase, lo realicé basándome en la técnica de crear una clase del compañero Francisco Peñalo Feliz pero con algunas variantes en la clase.

import 'package:flutter/material.dart';

class Rating extends StatelessWidget {

  double stars;

  Rating(this.stars);

  Widget getStars (){
    var list = <Widget>[];
    for (int i = 0; i < 5; i++){
      var icon = Icons.star;
      if (stars > 0 && stars < 1) {
        icon = Icons.star_half;
      } else if (stars <= 0) {
        icon = Icons.star_border;
      }
      var star = Container (
        margin: const EdgeInsets.only(
            top: 3.0,
            left: 5.0
        ),

        child: Icon(
          icon,
          color: const Color(0xFFf2C611),
          size: 13.0
        ),
      );
      list.add(star);
      stars--;
    }
    return Row(
        children: list
    );
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return getStars();
  }
} 

Con mas de tres comentarios me da error de overflow, pero sigo viendo como solucionarlo

//Reto 2
import 'package:flutter/material.dart';
import 'package:platzi_trips_app/review.dart';


class ReviewList extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build


   return Column(
     children: [
       Review("assets/img/adolecente.jpg", 'Juan Perez', '1 review 3 fotos', 'Es un hermoso lugar', 5),
       Review("assets/img/faraday3.jpg", 'Pedro Gomez', '1 review 2 fotos', 'Un lugar para apreciar la naturaleza', 3.5),
       Review("assets/img/jovenHombre.jpg", 'Arturo Lopez', '2 review 5 fotos', 'Precioso lugar', 3.0),
       Review("assets/img/spoke.jpg", 'Mr Spoke', '1 review 1 foto', 'Un lugar para apreciar el cielo', 4.0)
       
     ],
   );
  }

}

// review.dart
import 'package:flutter/material.dart';
import 'rate.dart';

class Review extends StatelessWidget{
  // String pathImage = "assets/img/jovenHombre";
  // String name = "Varuna Yasas";
  // String details = "1 review 5 photos";
  // String comment = "There is an amazing place in Sri Lanka";
  // double rating = 4.5;
  String pathImage ;
  String name ;
  String details ;
  String comment ;
  double rating ;
  //constructor de detalles

  Review(this.pathImage, this.name, this.details, this.comment, this.rating);



  @override
  Widget build(BuildContext context) {
    // TODO: implement build
// ----------------------------------------userComment
    final userComment = Container(
      margin: EdgeInsets.only(
          left: 20.0
      ),
      child:
      Text(
        comment,
        textAlign: TextAlign.left,
        style: TextStyle(
            fontFamily: "Lato",
            fontSize: 13.0,
            fontWeight: FontWeight.w900

        )
      ),
    );
//---------------------------------------------userInfo
    final userInfo = Row(
      //mainAxisSize: MainAxisSize.min,
      children: [
        Container(
          margin: EdgeInsets.only(left: 20.0),
          child: Text(
            details,
            textAlign: TextAlign.left,
            style: TextStyle(
                fontFamily: "Lato",
                fontSize: 13.0,
              color: Color(0xFFa3a5a7)
            )
          ),
        ),
        Rate(rating)
      ],
    );
//----------------------------------------------details
    final userName = Container(
      margin: EdgeInsets.only(
        left: 20.0,
      ),
      child: Text(
        name,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 17.0
        )
      ),
    );
//-----------------------------------------------UserDetails
    final userDatails = Flexible(
      child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        userName,
        userInfo,
        userComment

        ],
      ),
    );
//-------------------------------------------------Photo
    final photo = Container(

      margin: EdgeInsets.only(
        top: 10.0,
        left: 10.0
      ),
      width: 60.0,
      height: 60.0,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
          fit: BoxFit.cover,
          image: AssetImage(pathImage)
        )
      ),
    );



    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        photo,
        userDatails
      ],
    );
  }

}



Buenas tardes chicos,

Les comparto mi desafio:
![](https://github.com/JohanRiv/Flutter_Basic_Platzi_project.git

class ReviewList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    List<Review> listReview = new List<Review>();

    listReview.add(new Review("assets/img/avatar.png",
        "Goergina LaFuerte",
        "1 review 5 photos",
        "The Rivers of Sri Lanka originate in the central highlands. From there they descend to the plains and empty into the sea. "
    ));

    listReview.add(new Review("assets/img/avatar.png",
        "Goergina LaFuerte",
        "1 review 5 photos",
        "The Rivers of Sri Lanka originate in the central highlands. From there they descend to the plains and empty into the sea. "
    ));

    listReview.add(new Review("assets/img/avatar.png",
        "Goergina LaFuerte",
        "1 review 5 photos",
        "The Rivers of Sri Lanka originate in the central highlands. From there they descend to the plains and empty into the sea. "
    ));

    return Column(
      children: listReview
    );
  }
}

No se me presenta la informaciòn del commentario

muy bueno!

¡Así lo hice!

Super!!

Reto Cumplido! Agregue dos clases para evitar repetir código al crear los iconos de estrellas y texto, de esta forma:

icon_content.dart

import 'package:flutter/material.dart';

class IconContent extends StatelessWidget {

  final EdgeInsets margin;
  final IconData icon;
  final Color color;
  final double size;

  IconContent(
    this.margin,
    this.icon,
    this.color,
    this.size
  );

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: margin,
      child: Icon(
        icon,
        color: color,
        size: size,
      ),
    );
  }

}

text_content.dart

import 'package:flutter/material.dart';

class TextContent extends StatelessWidget {

  final String text;
  final EdgeInsets margin;
  final double fontSize;
  final Color fontColor;
  final FontWeight fontWeight;

  TextContent(
    this.text,
    this.margin,
    this.fontSize,
    this.fontColor,
    this.fontWeight
  );

  @override
  Widget build(BuildContext context) {
    
    return Container(
      margin: margin,

      child: Text(
        text,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: fontSize,
          color: fontColor
        ),
      ),
    );
  }

}

Y al utilizarlo en el review.dart queda asi (en los comentarios dejo el código que sustitui con las nuevas clases creadas):

import 'package:flutter/material.dart';
import 'components/text_content.dart';
import 'components/icon_content.dart';

class Review extends StatelessWidget {

  final String name;
  final int reviewsCount;
  final int photosCount;
  final String comment;
  final String pathImage;

  Review(
    this.name, 
    this.reviewsCount,
    this.photosCount,
    this.comment,
    this.pathImage
  );

  @override
  Widget build(BuildContext context) {

    final photo = Container( 
      margin: EdgeInsets.only(
        top: 20,
        left: 20
      ),

      width: 80,
      height: 80,

      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
          fit: BoxFit.cover,
          image: AssetImage(pathImage)
        )
      ),
    );

    final userName = TextContent(
      name, 
      EdgeInsets.only(
        top: 0, 
        left: 20, 
      ),
      17, 
      Colors.black,
      FontWeight.normal
    );
    
    /*final userName = Container(
      margin: EdgeInsets.only(
        left: 20,
      ),

      child: Text(
        name,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 17,
        ),
      ),
    );*/

    final emptyStar = IconContent(
      EdgeInsets.only( 
        left: 10, 
      ),
      Icons.star_border, 
      Color(0xfff2c611),
      11
    );

    /* final emptyStar = Container(
      margin: EdgeInsets.only(
        top: 23,
        right: 3
      ),
      child: Icon(
        Icons.star_border,
        color: Color(0xfff2c611)
      ),
    ); */

    final halfStar = IconContent(
      EdgeInsets.only(
        left: 10,
      ),
      Icons.star_half, 
      Color(0xfff2c611),
      11
    );

    /*final halfStar = Container(
      margin: EdgeInsets.only(
        top: 23,
        right: 3
      ),
      child: Icon(
        Icons.star_half,
        color: Color(0xfff2c611)
      ),
    );*/

    final fullStar = IconContent(
      EdgeInsets.only(
        left: 10,
      ),
      Icons.star, 
      Color(0xfff2c611),
      11
    );

    /*final fullStar = Container(
      margin: EdgeInsets.only(
        top: 23,
        right: 3
      ),
      child: Icon(
        Icons.star,
        color: Color(0xfff2c611)
      ),
    );*/

    final userInfo = Row(
      children: <Widget>[
        TextContent(
          '$reviewsCount reviews - $photosCount photos', 
          EdgeInsets.only( 
            left: 20, 
          ),
          13, 
          Color(0xFFa3a5a7),
          FontWeight.normal
        ),
        fullStar,
        fullStar,
        fullStar,
        halfStar,
        emptyStar
      ]
    );
    
    /*final userInfo = Container(
      margin: EdgeInsets.only(
        left: 20,
      ),

      child: Text(
        '$reviewsCount reviews - $photosCount photos',
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 13,
          color: Color(0xFFa3a5a7)
        ),
      ),
    );*/

    final userComment = TextContent(
      comment, 
      EdgeInsets.only( 
        left: 20, 
      ),
      13, 
      Colors.black,
      FontWeight.w900
    );

    /*final userComment = Container(
      margin: EdgeInsets.only(
        left: 20,
      ),

      child: Text(
        comment,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: "Lato",
          fontSize: 13,
          fontWeight: FontWeight.w900
        ),
      ),
    );*/

    final userDetails = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        userName,
        userInfo,
        userComment
      ],
    );

    return Row(
      children: <Widget>[
        photo,
        userDetails
      ],
    );
  }

}

Tuve que quitarle el margin top del description_place para que pudiera caber todo, porque no puedo hacer scroll. Y no se como subir una captura de mi telefono aquí, estoy en la laptop.

Para esta parte, lo primero que se me ocurrió fue jugar con los constructores. Investigando esta parte, decidí utilizar rápidamente un named constructor para diferencia el tipo de formato de estrella.

final starsW = new Stars.small(numberOfStars);

    final userInfoStars = Row(
      children: <Widget>[
        userInfo,
        starsW
      ],
    );

class Stars extends StatelessWidget {

  double numberOfStars;
  double starSize;

  Stars(this.numberOfStars){
    this.starSize = 24.0;
  }

  Stars.small(this.numberOfStars){
    this.starSize = 12.0;
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> rowStars = [];
    for(int i=1; i<=5; i++){
      rowStars.add(new Star(numberOfStars, starSize));
      numberOfStars--;
    }

    return new Row(
      children: rowStars,
    );
  }
}
class Star extends StatelessWidget {

  double numberOfStars;
  double starSize;

  Star(this.numberOfStars, this.starSize);

  @override
  Widget build(BuildContext context) {
    final marginRight = getMarginRightByStarSize(starSize);

    return new Container(
      margin: EdgeInsets.only(
          right: marginRight
      ),
      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),
      size: starSize,
    );
  }

  Widget halfStarIconWidget(){
    return new Icon(
      Icons.star_half,
      color: Color(0XFFF2C611),
      size: starSize,
    );
  }

  Widget emptyStarIconWidget(){
    return new Icon(
      Icons.star_border,
      color: Color(0XFFF2C611),
      size: starSize,
    );
  }

  double getMarginRightByStarSize(double starSize){
    if(starSize == 12.0){
      return 0.5;
    }

    return 3.0;
  }
}

Hice lo básico.

Y este es el resultado:

Resultado:

Parte del código:
review_list.dart

import 'package:flutter/material.dart';
import 'review.dart';

class ReviewList extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    return Column(
      children: <Widget>[
        new Review('graphics/traveler_profile.jpeg', 'Varunna Yasas', '1 review 5 Photos', 3.5, 'There is a amazing place in Sri Lanka'),
        new Review('graphics/traveler_profile_2.jpg', 'miler6', '1 review 6 Photos', 4.5, 'Ok, This trip was my first to GBI and for traveling abroad so I might be a little long winded'),
        new Review('graphics/traveler_profile_3.jpg', 'csf2024', '4 review 7 Photos', 3.0,  'I went on vacation to the grand bahama island in march 2008. I basically just got back. There were 7 of us who went. I t was alot of fun. Most of all it was extreamly relaxing'),
      ],
    );
  }

}

review.dart

import 'package:flutter/material.dart';
import 'star.dart';

class Review extends StatelessWidget{

  String pathImage = 'graphics/traveler_profile.jpeg';
  String userNameStr = 'Varunna Yasas';
  String detail = '1 review 5 Photos';
  String comment = 'There is a amazing place in Sri Lanka';
  double review;

  Review(this.pathImage, this.userNameStr, this.detail, this.review, this.comment);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    final userName = Container(
      margin: EdgeInsets.only(
          left: 20.0
      ),

      child: Text(
        userNameStr,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: 'Lato',
          fontSize: 17.0,
        ),
      ),

    );

    final userInfo = Container(
      margin: EdgeInsets.only(
          left: 20.0,
          right: 3.0
      ),

      child: Center(
        child: Text(
        detail,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontFamily: 'Lato',
          fontSize: 13.0,
          color: Color(0xFFa3a5a7)
        ),
      ),
      )
    );

    final userReview = Row(
      children: Star.generateStarList(review, true)
    );

    final userComment = Container(
      margin: EdgeInsets.only(
          left: 20.0,
          right: 20.0
      ),

      child: Text(
        comment,
        textAlign: TextAlign.left,
        overflow: TextOverflow.ellipsis,
        maxLines: 3,
        style: TextStyle(
            fontFamily: 'Lato',
            fontSize: 12.0,
            fontWeight: FontWeight.w900
        ),
      ),

    );


    final userDetail = Flexible(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            userName,
            Row(
              children: <Widget>[
                userInfo,
                userReview
              ],
            ),
            userComment
      ],)
    );

    final photo = Container(

      margin: EdgeInsets.only(
        top: 20.0,
        left: 20.0,
      ),

      width: 80.0,
      height: 80.0,

      decoration: BoxDecoration(
        shape: BoxShape.circle,
        image: DecorationImage(
            fit: BoxFit.cover,
            image: AssetImage(pathImage)
        ),
      ),

    );

    return Row(
      children: <Widget>[
        photo,
        userDetail
      ],
    );
  }

}

![](

Exito!!!

¡Hey! ¿cómo puedo hacer lo de las estrellas en las reviews, por favor? He tratado de colocarlas pero se sobreponen sobre otros textos o simplemente no me sale bien. 😦

Saludos,

Cree una clase Star, para el manejo de las estrellas, incluyendo un método estático para generar la lista de estrellas:

import 'package:flutter/material.dart';

enum StarType {border, half, full}

class Star extends StatelessWidget {
  StarType starType;

  Star(this.starType);

  _icon() {
    switch (starType) {
      case StarType.border:
        return Icons.star_border;
      case StarType.half:
        return Icons.star_half;
      case StarType.full:
        return Icons.star;
      default:
        return Icons.stars;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Icon(
        _icon(),
        color: Color(0xfff2c611),
      ),
    );
  }

  static list(int total, int selected) {
    var stars = List.generate(selected, (x) => Star(StarType.full));
    stars.addAll(List.generate(total - selected, (x) => Star(StarType.border)));
    return stars;
  }

}

Modifiqué la clase Review para usar la nueva clase Star:

import 'package:flutter/material.dart';
import 'star.dart';

class Review extends StatelessWidget {
  String pathImage = 'assets/img/people.jpg';
  String name = 'Varuna Yasas';
  String details = '1 review, 5 photos';
  String comment = 'There is an amazing place in Sri Lanka.';
  int stars = 5;

  Review({this.pathImage, this.name, this.details, this.comment, this.stars});

  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    final photo = Container(
      margin: EdgeInsets.only(
        top: 20.0,
        left: 20.0,
      ),
      width: 80.0,
      height: 80.0,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.black,
        image: DecorationImage(
          image: AssetImage(pathImage),
          fit: BoxFit.cover,
        ),
      ),
    );

    final userName = Container(
      margin: EdgeInsets.only(
        left: 20.0,
      ),
      child: Text(
        name,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontSize: 17.0,
          fontFamily: 'IBM Plex Sans',
        ),
      ),
    );

    final userInfo = Container(
      margin: EdgeInsets.only(
        left: 20.0,
      ),
      child: Text(
        details,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontSize: 13.0,
          fontFamily: 'IBM Plex Sans',
          color: Color(0xffa3a5a7),
        ),
      ),
    );

    final userComment = Container(
      margin: EdgeInsets.only(
        left: 20.0,
      ),
      child: Text(
        comment,
        textAlign: TextAlign.left,
        style: TextStyle(
          fontSize: 13.0,
          fontFamily: 'IBM Plex Sans',
          fontWeight: FontWeight.w900,
        ),
      ),
    );

    final userDetails = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Row(
          children: <Widget>[
            userName,
            Row(
              children: Star.list(5, stars),
            )
          ],
        ),
        userInfo,
        userComment,
      ],
    );

    return Row(
      children: <Widget>[
        photo,
        userDetails,
      ],
    );
  }
}

Y por último, la clase ReviewList que me devuelve la lista de Reviews en columna:

import 'package:flutter/material.dart';
import 'review.dart';

class ReviewList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      children: <Widget>[
        Review(
          pathImage: 'assets/img/alpha.png',
          name: 'Alfa',
          details: '1 me gusta, 2 no me gusta',
          comment: 'Esta es la letra griega Alfa.',
          stars: 2,
        ),
        Review(
          pathImage: 'assets/img/beta.png',
          name: 'Beta',
          details: '1 me gusta, 2 no me gusta',
          comment: 'Esta es la letra griega Beta.',
          stars: 4,
        ),
        Review(
          pathImage: 'assets/img/gamma.png',
          name: 'Gama',
          details: '1 me gusta, 2 no me gusta',
          comment: 'Esta es la letra griega Gama.',
          stars: 1,
        ),
      ],
    );
  }
}

SABE ALGUIEN EL ENLACE DEL GITHUB POR QUE DESCARGO Y NADA

Código para los demás reviews:

import 'package:flutter/material.dart';
import 'package:platzi_trips_app/review.dart';

class ReviewList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      children: <Widget>[
        Review('\assets\images\people.jpg','Verona Yasas',"1 review 5 photos",'There is an amazing place'),
        Review('\assets\images\people2.jpg','Julio Casas',"3 review 4 photos",'I have not visit it yet, but it looks like a beautiful place'),
        Review('\assets\images\people3.jpg','Maria Lucia',"7 review 3 photos",'Wonderfull landscape, but very hot'),
      ],
    );
  }
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'review.dart';

class ReviewList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Review("assets/images/corte_cachetada.jpg", "Luis Felipe", "1 review 5 photos", "Corte muy bueno, recomendable."),
        Review("assets/images/corte_raya.jpg", "Fernando Casas", "2 review 4 photos", "Corte muy bueno, recomendable."),
        Review("assets/images/corte_degradado.jpg", "Gorge Garcia", "3 review 6 photos", "Corte muy bueno, recomendable."),
        Review("assets/images/corte_colita.png", "Juan Córdova", "5 review 3 photo", "Corte muy bueno, recomendable.")
      ],
    );
  }

}```

Reto cumplido!

Ya espero con ansias el curso avanzado!

Alguien sabe como justificar el texto?

final userComment = Container(
      margin: EdgeInsets.only(
        right: 20.0,
        top: 5.0,
        left: 20.0,
      ),
      child: Text(comment,
        style: const TextStyle(
          fontFamily: "Lato",
          fontWeight: FontWeight.w500,
          fontSize: 13.0,
        ),
        textAlign: TextAlign.justify,
      ),
    );```

el min 7:36 … fue accidental o es para ponernos a “prueba” ??

No scrolled 😦 :
.

Scrolled 😄 :
.

Yeah! 😃

La calificación dinamica gracias a @David Andres Carrera Pineda 👍

Cree una funcion completa para maneras las estrellas y cree una carpeta llamada controllers donde solo utilizo funciones 😃

 

import 'package:flutter/material.dart';

// ignore: camel_case_types
class stars {
  static Widget drawStars(
      double numberStars, double marginTop, double marginLeft) {
    List<Widget> rowStars = [];

    for (var i = 0; i < 5; i++) {
      rowStars.add(starWidget(numberStars, marginTop, marginLeft));
      numberStars--;
    }

    return Row(
      children: rowStars,
    );
  }

  static Widget starWidget(
      double valueStar, double marginTop, double marginLeft) {
    return Container(
      margin: EdgeInsets.only(top: marginTop, right: marginLeft),
      child: validateStarIconWidget(valueStar),
    );
  }

  static Widget validateStarIconWidget(double pointStar) {
    if (pointStar >= 1.0) {
      return fullStarIconWidget();
    }

    if (pointStar >= 0.5) {
      print(pointStar);
      return halfStarIconWidget();
    }

    return emptyStarIconWidget();
  }

  static Widget fullStarIconWidget() {
    return new Icon(
      Icons.star,
      color: Color(0XFFF2C611),
    );
  }

  static Widget halfStarIconWidget() {
    return new Icon(
      Icons.star_half,
      color: Color(0XFFF2C611),
    );
  }

  static Widget emptyStarIconWidget() {
    return new Icon(
      Icons.star_border,
      color: Color(0XFFF2C611),
    );
  }
}

 

Aqui el reto!
 

review_list.dart
 
 

import 'package:flutter/material.dart';
import 'package:platzi_flutter/pages/review.dart';

class ReviewList extends StatelessWidget {
  final url =
      "https://images.unsplash.com/photo-1599302761127-e3ed900207fd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=400&q=80";

  @override
  Widget build(BuildContext context) {
    return Column(
      children: listReview(),
    );
  }

  List<Widget> listReview() {
    List<Widget> contenedor = [];

    for (var i = 0; i < 5; i++) {
      contenedor.add(Review(
        url,
        "Varuna Yasas",
        "There is a amazing place in Sri Lanka",
        5.0,
      ));
    }

    return contenedor;
  }
}

 
 

Review.dart

 
 

import 'package:flutter/material.dart';
import '../controllers/stars.dart';

// ignore: must_be_immutable
class Review extends StatelessWidget {
  final String pathImage;
  final String userName;
  String details = "1 review 5 photos";
  final String comment;
  final double pointStars;
  double _spacing = 5.0;

  Review(this.pathImage, this.userName, this.comment, this.pointStars);

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        _foto(),
        _userDetails(),
      ],
    );
  }

  Widget userComment() {
    return Container(
      margin: EdgeInsets.only(left: 20.0, top: _spacing),
      child: Text(
        comment,
        style: TextStyle(
            fontFamily: 'Lato',
            fontSize: 17.0,
            color: Colors.black,
            fontWeight: FontWeight.w900),
      ),
    );
  }

  Widget userInfo() {
    return Container(
      margin: EdgeInsets.only(left: 20.0, top: _spacing),
      child: Text(
        details,
        style: TextStyle(
            fontFamily: 'Lato', fontSize: 17.0, color: Color(0xFFa3a5a7)),
      ),
    );
  }

  Widget userInfoAndStars() {
    return Row(
      children: <Widget>[userInfo(), stars.drawStars(pointStars, 0, 3.0)],
    );
  }

  Widget _userName() {
    return Container(
      margin: EdgeInsets.only(left: 20.0, top: _spacing),
      child: Text(
        userName,
        textAlign: TextAlign.left,
        style: TextStyle(
            fontSize: 17.0,
            fontFamily: 'Lato',
            fontWeight: FontWeight.w900,
            color: Colors.black),
      ),
    );
  }

  Widget _userDetails() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[_userName(), userInfoAndStars(), userComment()],
    );
  }

  Widget _foto() {
    return Container(
      margin: EdgeInsets.only(top: 20.0, left: 20.0),
      width: 80.0,
      height: 80.0,
      child: CircleAvatar(
        backgroundImage: NetworkImage(pathImage),
      ),
    );
  }
}

:S 😃

Para que no tengan que Hardcodear las estrellas, escribí este Widget, que recibe como parámetro la cantidad de estrellas que va a desplegar y el score que el usuario le dio. Esto te genera de manera Automatica un Row con las estrellas que necesitas.

import 'package:flutter/material.dart';

class StarList extends StatelessWidget {
  int numberStars;
  double score;

  StarList(this.numberStars, this.score);

  @override
  Widget build(BuildContext context) {
    final starHalf = Container(
      margin: EdgeInsets.only(
        right: 3.0,
      ),
      child: Icon(
        Icons.star_half,
        color: Color(0xFFF2C611),
      ),
    );

    final starBorder = Container(
      margin: EdgeInsets.only(
        right: 3.0,
      ),
      child: Icon(
        Icons.star_border,
        color: Color(0xFFF2C611),
      ),
    );

    final star = Container(
      margin: EdgeInsets.only(
        right: 3.0,
      ),
      child: Icon(
        Icons.star,
        color: Color(0xFFF2C611),
      ),
    );

    List<Widget> listStars = [];
    listStars.addAll(List.filled(score ~/ 1, star));
    if (score % 1 == 0.5) {
      listStars.add(starHalf);
    }
    listStars.addAll(List.filled(numberStars - listStars.length, starBorder));

    return Row(
      children: [...listStars],
    );
  }
}

Por que esta vez si pasa por el constructor las variables normales de texto como comment, details y name y en la la clase anterior description_place no lo hace ? cual es la diferencia ?

Asi quedo mi ReviewList

class ReviewList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    List<Review> reviewList = [
      Review("assets/images/people.webp", "Manuel Zambrano",
          "3 review 6 photos", "What an amazing place!"),
      Review("assets/images/youngBoy.jfif", "Valeria Rodriguez",
          "1 reviews 2 photos", "Love those beaches"),
      Review("assets/images/guy.jfif", "Jose Di Pietro", "4 reviews 3 photos",
          "Nice place!"),
    ];
    return Column(children: reviewList);
  }
}

Hice widgets aparte para controlar el rating y tenerlo un poco mas dinámico

Widget showStars(double numStars, [double size = 24]) {
  List<Widget> starsToShow = [];
  List(numStars.truncate()).forEach((i) => starsToShow.add(star(1, size)));
  if (numStars.remainder(numStars.truncate()).ceil() >= 1) {
    numStars++;
  }
  List(numStars.remainder(numStars.truncate()).ceil())
      .forEach((i) => starsToShow.add(star(2, size)));
  List((numStars.truncate() - 5).abs())
      .forEach((i) => starsToShow.add(star(3, size)));

  return Row(
    children: starsToShow,
  );
}

Widget star(int type, double size) {
  return Container(
      margin: EdgeInsets.only(right: 3.0),
      child: Icon(
          type == 1
              ? Icons.star
              : type == 2
                  ? Icons.star_half
                  : Icons.star_border,
          color: Color(0xFFf2c611),
          size: size));
}

Despues de tardar 30 min, para darme cuenta que tenia en el star un margintop pude arreglarlo jejej. Nunca copien y peguen asi nada mas…

Aún no hago el ListReview…