Convierte tus ideas en apps

Crear Vista Para Mostrar Porcentaje De Calificaciones Y Reseñas Con SwiftUI

Crear Vista Para Mostrar Porcentaje De Calificaciones Y Reseñas con switUI

¿Para que necesito un ratingView?

En mi caso le llamare RatingView, esto hace referencia a un listado de estrellas en dirección horizontal(que también puede ser cualquier figura) que muestra el porcentaje de calificación respecto al total de reseñas que tienen nuestras publicaciones(un producto, una foto, etc). Esto normal mente se añaden en las CardView(vista previa con algo de información de alguna publicación) , También necesitaremos esta vista para poder dar la opción al usuario de valorar publicaciones, pero en este caso esta vista tendría que ser interactiva y para añadirla a una CardView solo la utilizaremos para mostrar la antes mencionada información .

Crear RatingView

Existen muchas maneras de llevar acabo este tipo de vista incluso el nombre será distinto yo en mis programas le llamo así, también puede ser que otros desarrolladores lo hagan de distinta manera, pero se trata de ser creativo, de la manera en la que nosotros lo haremos será utilizando SwiftUI lo haremos de una manera muy sencilla y con pocas lineas de código y una vez que lo hagamos podremos reutilizarla en cualquier proyecto.

A continuación abrimos Xcode y creamos un nuevo proyecto y ponemos el nombre que queramos, luego de esto crearemos un nuevo fichero llamado RatingView.

Variables para Recibir los Parámetros de Nuestra vista

Necesitaremos recibir unos valores para que nuestras vista se puede personalizar al reutilizarla en cualquier proyecto, la constante “percentage” representa el valor que se mostrará de manera gráfica, mainColor es para darle el color principal y secundaryColor para dar el valor del color secundario, la ultima variable de tipo Bool es para asignar un borde a cada estrella, esto nos quedara mas claro al finalizar.

let percentage: Double

var mainColor: Color = .yellow

var secundaryColor: Color = .gray.opacity(0.5)

var addBorders: Bool = false

Implementar código para dar forma a la vista deceada

Luego dentro de las llaves de la variable body crearemos un GeometryReader y dentro del GeometryReader declararemos dos constantes con los valores que retorna la el ancho y el alto global del mismo.

GeometryReader { proxy in

            let width = proxy.frame(in: .global).width

            let height = proxy.frame(in: .global).height

}

El contenido del GeometryReader sera una pila de vista hacia el eje z ósea un ZStack. Le asignamos el color secundario que equivale al antes declarado, el color secundario es el que remarca todo el fondo que posteriormente al agregar el color primario dará el efecto de llenar la barra de estrellas según el porcentaje que le pasemos a nuestra constante “percentage”, que se vea que aparentemente la barra de estrellas se rellena del color principal, a mainColor le diremos que su ancho sera  el ancho de su ámbito(GeometryReader) por el porcentaje recibido  y este resultado lo dividimos entre 100, también tenemos que asignar un alto que será también el de su ámbito.

GeometryReader { proxy in

            let width = proxy.frame(in: .global).width

            let height = proxy.frame(in: .global).height

            ZStack(alignment: .leading) {

                secundaryColor

                mainColor

                    .frame(width: (width)*percentage/100, height: height)

                if addBorders {

                    HStack(spacing: 1) {

                        ForEach(0..<5) { _ in

                            Image(systemName: «star»)

                                .resizable()

                                .scaledToFit()

                        }

                    }

                }

            }

         }

Hasta el momento tendríamos solo dos rectángulos superpuestos uno de color gris y otro de color amarillo(Puede ser cualquier color), Para poder verlo vamos agregar nuestra vista RatingView a ContentView, cuando lo agreguemos nos pedirá que le pacemos un valor a “percentage” el valor puede ser cualquier menos de 100, también le daremos un alto de 40  para que ho se redimensione al alto de toda la pantalla.

struct ContentView: View {

    var body: some View {

        RatingView(percentage: 30)

            .frame(height:40)

    }

}

Darle forma al Rectángulo

Antes de darle forma quitaremos el alto que le dimos en ContentView y le daremos un ancho o simplemente quitamos el mitificado .frame. 

struct ContentView: View {

    var body: some View {

        RatingView(percentage: 30)

    }

}

Para darle forma de cinco estrellas continuas en dirección horizontal, simplemente tendremos agregar una mascara a nuestro ZStack. Definiremos nuestra mascara con un HStack, dentro del HStack implementaremos un ForEach para que regenere 5 imágenes de estrella. En este caso utilizaremos una imagen del sistema.

            GeometryReader { proxy in

            let width = proxy.frame(in: .global).width

            let height = proxy.frame(in: .global).height

            ZStack(alignment: .leading) {

                secundaryColor

                mainColor

                    .frame(width: (width)*percentage/100, height: height)

            }

            .mask {

                HStack(spacing: 1) {

                    ForEach(0..<5) { _ in

                        Image(systemName: «star.fill»)

                            .resizable()

                            .scaledToFit()

                    }

                }

            }

RatingView

Listo ya tenemos nuestro RatingView. Una cosas de las que tenemos que tener en cuenta es que el porcentaje que le demos siempre tendrá que ser lógica mente menos de 100, este porcentaje lo calcularemos de la siguiente manera: (total de calificaciones * (total de reseñas * 5) ) / 100, En otro tutorial aprenderemos a crear una CardView utilízanos esta vista de calificaciones también incluiremos una estructura de datos para hacerlo mas parecido a un caso real, con  distintas reseñas.

Agregar Opción de Personalización

Vamos agregar la opción de darle bordes a cada una de las cinco estrellas, lo haremos declarando una sentencia “if” utilizando la variable de tipo Bool que declaramos al principio var addBorders: Bool = false , luego copiaremos el HStack con todo lo que contiene dentro de sus llaves y lo pegaremos dentro de la sentencia “if” lo único  que cambiaremos sera el nombre de la imagen del sistema «star.fill» por «star». Luego vamos al ContentView y añadimos el parámetro “addBorders”  de nuestro RatingView y le damos el valor true desde allí también podemos cambiar los colores el principal y el secundario. Esto se vera de la siguiente manera:

GeometryReader { proxy in

            let width = proxy.frame(in: .global).width

            let height = proxy.frame(in: .global).height

            ZStack(alignment: .leading) {

                secundaryColor

                mainColor

                    .frame(width: (width)*percentage/100, height: height)

                if addBorders {

                    HStack(spacing: 1) {

                        ForEach(0..<5) { _ in

                            Image(systemName: «star»)

                                .resizable()

                                .scaledToFit()

                        }

                    }

                }

            }

            .mask {

                HStack(spacing: 1) {

                    ForEach(0..<5) { _ in

                        Image(systemName: «star.fill»)

                            .resizable()

                            .scaledToFit()

                    }

                }

            }

        }

285E207F-285C-4349-9A02-0C0082398885

Listo ya tendríamos nuestra vista terminada solo una cosa mas, lo ideal y lo lógico seria que el borde tuviera el color principal para esto tendremos que escribir una ultima linea de código que seria la siguiente: .foregroundColor(mainColor), este modificador lo vamos a colocar en el ZStack antes del modificador .mask, nuestro código y nuestra vista acabada por completo  se verían así.

struct RatingView: View {

    let percentage: Double

    var mainColor: Color = .yellow

    var secundaryColor: Color = .gray.opacity(0.5)

    var addBorders: Bool = false

    var body: some View {

        GeometryReader { proxy in

            let width = proxy.frame(in: .global).width

            let height = proxy.frame(in: .global).height

            ZStack(alignment: .leading) {

                secundaryColor

                mainColor

                    .frame(width: (width)*percentage/100, height: height)

                if addBorders {

                    HStack(spacing: 1) {

                        ForEach(0..<5) { _ in

                            Image(systemName: «star»)

                                .resizable()

                                .scaledToFit()

                        }

                    }

                }

            }

            .foregroundColor(mainColor)

            .mask {

                HStack(spacing: 1) {

                    ForEach(0..<5) { _ in

                        Image(systemName: «star.fill»)

                            .resizable()

                            .scaledToFit()

                    }

                }

            }

        }

    }

}

E3ECF6EC-CA97-459E-BD0F-676C9A7D3091

Bien hemos terminado de crear una vista muy sencilla pero muy util, este código lo encontraras en mi perfil de GitHub, abajo te dejo el link. si te gusto el tutorial deja un comentario que para mi es de mucho valor cualquier critica me servirá a mejorar, si crees que al tutorial le falto algo házmelo saber que estaré muy agradecido nos vemos en otro tutorial. 

¡Hasta luego!



Obtener código en GitHub

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *