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 widgetreview, y luego del widgetreviewList.
Presta especial atención al uso de los widgetsText 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 widgetColumn(), que como ya hemos visto en clases anteriores, nos permite organizar los widgets hijos unos arriba de los otros en el eje Y.
Utilicé la clase Rating en la clase de Review para generar las estrellas.
review.dart
import'package:flutter/material.dart';import'rating.dart';classReviewextendsStatelessWidget{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
Widgetbuild(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),)),);returnRow(children:<Widget>[ photo, userDetails,],);}}
Muy buen aporte frank, modifiqué tu clase para que el color de la estrella cambie cuando es medio punto en el rating.
Buen aporte Frank modifique un poco la clase rating.
import'package:flutter/material.dart';classRatingextendsStatelessWidget{constRating({Key? key, required this.stars, required this.marginLeft, required this.fontSize, required this.marginRight, required this.marginTop,}):super(key: key); final double stars; final double marginLeft; final double marginRight; final double fontSize; final double marginTop;WidgetgetStar(double stars){var icon =Icons.star; stars ==0.5? icon =Icons.star_half: icon; stars <0.5? icon =Icons.star_border: icon;returnContainer(margin:constEdgeInsets.only(right:3.0),child:Icon( icon,color:constColor(0xFFff9100),size: fontSize,),);}WidgetgetRating(double stars){ final list =List<Widget>.generate(5,(index)=>getStar(stars - index));returnContainer(margin:EdgeInsets.only(left: marginLeft,right: marginRight,top: marginTop),child:Row(children: list,),);}
@override
Widgetbuild(BuildContext context){returngetRating(stars);}}
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.
como se llama ese emulador? es que me gusta el estilo
José Eduardo Guevara Soria Ese emulador solo esta disponible para macOS, en windows solo puedes tener emuladores android.
Cómo pusiste en el centro el titulo de la appbar en android?
@Jomach : en el main.dart dentro del build > home > appBar tenés que agregarle “centerTitle: true”, te quedaría así:
classMyAppextendsStatelessWidget{// This widget is the root of your application. @override
Widgetbuild(BuildContext context){returnMaterialApp(title:'Flutter Demo',theme:ThemeData(primarySwatch:Colors.blue,),home:Scaffold(appBar:AppBar(title:Text("Hola mundo"),centerTitle:true,),body:newDescriptionPlace("Bahamas",1, descriptionDummy),));}}```
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
Hola helard, llevaste ya e
Primero el curso de dart? Es necesario para este curso, recomiendo también el de Programación Orientado a Objetos y los pre requisitos de esos, en todo caso, igual podría responderte algunas dudas
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:
¡Gracias por el dato!
Muy buen dato, gracias.
Yo tambien tuve el mismo problema y lo solucione fue con el Widget
Expanded
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';classStarextendsStatelessWidget{// Numeros por default final int _defaultNumberStar =5; final double _defaultStarSize =14.0; final Color _defaultStarColor =constColor(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;constStar(this.stars,{this.color,this.starSize,this.margin,this.numberStar});
@override
Widgetbuild(BuildContext context){// TODO: implement buildreturnshowStars(stars);}Widgetstar(bool withBorder){returnContainer(margin: margin,child:Icon( withBorder ?Icons.star:Icons.star_border,size: starSize ?? _defaultStarSize,color: color ?? _defaultStarColor
),);}WidgetshowStars(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);returnRow(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.
Excelente. Muchas gracias por compartilo.
Interesante aporte, gracias k3entu.
Termine!
classReviewListextendsStatelessWidget{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
Widgetbuild(BuildContext context){returnColumn(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
Lo que sucede es que te pasaste del limite, puedes probar con reducir el texto o el tamaño del margin. Si es bottom, entonces reduces el top.
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';classReviewListextendsStatelessWidget{List<Review> lista =List<Review>();String title;String desc; dynamic stars;ReviewList(this.lista,this.title,this.desc,this.stars);
@override
Widgetbuild(BuildContext context){returnColumn(children:<Widget>[Description(title, stars, desc,30.0),getWidgets(lista),]);}ColumngetWidgets(List list1){List<Review> list =newList<Review>();for(int i =0; i < list1.length; i++){ list.add(list1[i]);}returnColumn(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),),);
Esto más que un curso explicando Flutter es un ejemplo para ver cómo se hace una aplicación👎🏼
hola como hiciste para el pubspec.yaml? podrias compartir ese codigo sobre todo para ver las versiones ya que me ha sido imposible subir imagenes no se si estoy con unas versiones mas recientes (segun lo que me sale en ingles ) pero no he dado con el chiste me he quedado estancado
Reto:
Mi solución:
/**Clase ReviewList**/import'package:flutter/material.dart';classReviewListextendsStatelessWidget{List<Widget> items =[];ReviewList(this.items); @override
Widgetbuild(BuildContext context){// TODO: implement build final reviewList =Column(children: items
);return reviewList;}}/**Clase Review**/import'package:flutter/material.dart';import'review_stars.dart';classReviewextendsStatelessWidget{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
Widgetbuild(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:newReviewStars(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';classReviewStarsextendsStatelessWidget{ num numStars =0; num iconSize =24;ReviewStars(this.numStars,this.iconSize);
@override
Widgetbuild(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';classDescriptionPlaceextendsStatelessWidget{String namePlace;String descriptionPlace; num numStars;List<Widget> reviewList =[];DescriptionPlace(this.namePlace,this.descriptionPlace,this.numStars);
@override
Widgetbuild(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:newReviewStars(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(newReview('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,newReviewList(reviewList)],);return _description_place;}}
Review list
classReviewListextendsStatelessWidget{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
Widgetbuild(BuildContext context){// TODO: implement buildreturnColumn(children:<Widget>[Review(pathImage, name, details, comment),Review(pathImage, name, details, comment)],);}}
Review
classReviewextendsStatelessWidget{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
Widgetbuild(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))),);returnRow(children:<Widget>[ photo, userDetails
],);}
Description place
final description_place =Column(children:<Widget>[ title_starts, description,newReviewList()],);