Un clon de Instagram usando SwiftUI y GraphQL – ProfileView

Hoy en la parte 3 de nuestra App clon de Instagram con GraphQL vamos a profundizar en SwiftUI, construyendo nuestra vista de Perfil.

Aprenderemos a reutilizar structs en SwiftUI y hablaremos de algunos controles: VStack, HStack, GeometryReader, Text, Button, Spacer, Image, Divider entre otros.

En nuestros artículos anteriores, aprendimos cómo dar de alta a un usuario y cómo loguear a un usuario, con las respectivas UIs en nuestra App clon de Instagram. Hoy lo haremos mucho más bonito.

Abróchense los cinturones y ¡manos a la obra!

Para un mejor aprendizaje, descarga el proyecto iOS Instagram Clone con el código fuente.

¿Quieres un comienzo rápido?

¡Clona esta App desde nuestro Hub y empieza a usarla sin problemas!

Qué vamos a construir exactamente

Vamos a construir la siguiente vista:

screen-shot-2019-09-16-at-10-08-35

SwiftUI hace que sea realmente fácil construir interfaces tan complejas, ya que puedes reutilizar un montón de componentes de forma muy fácil y sencilla.

Lo único es que debemos aprender a crear esos componentes reutilizables. Esa vista es en realidad una combinación de múltiples vistas que se integran en un resultado final.
Una lista simplificada de componentes es la siguiente:

screen-shot-2019-09-16-at-10-08-35

Donde:

  • VStack
  • Hstack
  • Controles reales (botones, divisores, etc)

HStack, Vstack, Zstack ¿qué?

SwiftUI construye sus UIs alineando las vistas verticalmente usando VStack (Vertical Stack) y horizontalmente usando HStack (Horizontal Stack) y superponiendo las vistas con Zstack (Z como en z-index).

Cada vez que necesite una vista debajo de otra, debe utilizar VStack.

Cada vez que necesites una vista al lado de otra, debes usar un HStack.

Cada vez que necesites una vista superpuesta a otra, debes usar una ZStack.

Como nuestra vista principal consistirá en muchas vistas colocadas horizontalmente una debajo de la otra, contendremos todo en la VStack principal y empezaremos desde ahí, pero hay una más que necesitaremos usar para ocupar toda la pantalla: el GeometryReader.

Nos permite renderizar todo en función de su tamaño y coordenadas (del GeometryReader).

Reutilización

La reutilización es una de las bellezas de SwiftUI, por lo que podemos crear controles complejos y reutilizarlos donde sea necesario.

Para esta aplicación, hay principalmente dos componentes que vamos a reutilizar en diferentes vistas: la línea de tiempo y la barra inferior:

screen-shot-2019-09-16-at-10-46-23

Por esta razón, vamos a crear los códigos de interfaz de usuario por separado para que sea más organizado. El resto del código UI específico para una vista puede permanecer en el archivo de código de esa vista.

Así que empecemos…

Creando nuestra vista de perfil

Añade un nuevo archivo SwiftUI y nómbralo ProfileView.swift.

Como vamos a alinear los componentes para llenar la pantalla, vamos a empezar añadiendo un GeometryReader para asegurarnos de que todos los controles en su interior utilizarán su tamaño y coordenadas:

struct ProfileView: View {
    var body: some View {
        GeometryReader { geometría en
            
        }
    }
}

Ahora, nuestra vista se integrará en un VStack principal que contendrá todos nuestros controles, así que añadámoslo también

struct VistaPerfil: View {
    var body: some View {
        GeometryReader { geometría en
            VStack{
                
            }
        }
    }
}

Y nuestra primera “línea” de controles será la superior:

screen-shot-2019-09-16-at-10-53-00

Lo que parece una simple línea de controles es en realidad múltiples controles:

  • el texto “nombre de usuario
  • la pequeña flecha apuntando hacia abajo junto a él
  • un espaciador para rellenar el espacio entre la flecha y el siguiente control
  • un botón de hamburguesa a la derecha

Utilizaremos iconos para los botones, así que asegúrate de encontrar algunos iconos gratuitos. Un buen lugar para encontrarlos es Freepik.

Así que, vamos a añadir nuestro HStack:

struct ProfileView: View {
    var body: some View {
        GeometryReader { geometría en
            VStack{
                HStack{
                    
                }
            }
        }
    }
}

Y en él, nuestro primer Texto:

struct VistaPerfil: View {
    var body: some View {
        GeometryReader { geometría en
            VStack{
                HStack{
                    Texto("nombre de usuario")
                }
            }
        }
    }
}

Hasta aquí probablemente te trajo a esto:

screen-shot-2019-09-16-at-10-59-56

Muy bien. Es un comienzo.

Vamos a alinearlo a la izquierda añadiendo un

(alineación: .leading)

a nuestro VStack:

struct ProfileView: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombre de usuario")
                }
            }
        }
    }
}

También podemos añadir algunas propiedades Text para hacerlo más consistente con nuestro diseño:

Para establecer su color a nuestro lightBlueColor que está definido en nuestro AppDelegate:

.foregroundColor(lightBlueColor)

Para cambiar el peso de la fuente:

.fontWeight(.semibold)

Y por último para añadir algo de padding (espacio) en la parte inicial:

.padding(.leading, 10)

Y tu código ahora debería verse así

struct PerfilVista: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                    .fontWeight(.semibold)
                    .padding(.leading, 10)
                }
            }
        }
    }
}

Y tu UI debería verse así:

screen-shot-2019-09-16-at-11-07-31

Ahora vamos a añadir ese pequeño botón de flecha.

Como aprendiste en la Parte 2 de este artículo, añade la imagen de la flecha hacia abajo para nuestro botón, y añadamos el botón a nuestro código SwiftUI:

Button(acción: {}){
    
}

Y añadimos nuestra imagen en él:

Botón(acción: {}){
    Imagen("flecha-abajo")
    .redimensionable()
    .frame(ancho: 10, alto: 10)
}

Y sólo por alineación, vamos a añadir un poco de relleno en la parte superior:

Button(acción: {}){
    Imagen("flecha-abajo")
    .redimensionable()
    .frame(ancho: 10, alto: 10)
}
.padding(.top, 5)

Nuestro código completo debería ser ahora así

struct PerfilVista: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                    .fontWeight(.semibold)
                    .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                }
            }
        }
    }
}

Y nuestra UI:

screen-shot-2019-09-16-at-11-28-48

Ahora vamos a añadir el botón hamburguesa de la misma manera:

Botón(acción: {}){
    Imagen("menu")
    .redimensionable()
    .frame(anchura: 20, altura: 20)
}.padding()

Nuestro código completo:

struct PerfilVista: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                    .fontWeight(.semibold)
                    .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                }
            }
        }
    }
}

Y nuestra vista:

screen-shot-2019-09-16-at-11-31-17

Si sólo hubiera algo que pudiéramos poner entre esos dos botones para tomar todo el espacio entre ellos y alinear todo…

Espaciador()

¡Ahora se ve bien!

Nuestro código completo hasta ahora:

struct ProfileView: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                    .fontWeight(.semibold)
                    .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Espaciador()
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                }
            }
        }
    }
}

Y ahora vamos a fijar la altura de ese HStack y darle un poco de relleno en la parte delantera, y estamos listos para ir:

.frame(height: 50)
.padding(.leading, 10)

Código completo:

struct ProfileView: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                    .fontWeight(.semibold)
                    .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Espaciador()
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                .frame(altura: 50)
                .padding(.leading, 10)
            }
        }
    }
}

Ahora podemos empezar nuestro…

Segunda HStack

Como hemos creado todo dentro de una VStack principal, cada nuevo control que añadamos fuera de esa primera HStack se pondrá automáticamente debajo de ella.

Así que es hora de hacer nuestra segunda HStack y construir la segunda parte de nuestra pantalla:

screen-shot-2019-09-16-at-12-01-35

Esta también será una HStack, conteniendo 4 VStacks en su interior: una para la Imagen y el texto debajo de ella, y 3 para los números con texto debajo de ellos.

Como probablemente ya has entendido el concepto, te dejo el código completo de esta nueva HStack:

HStack{
    VStack{
        Imagen("logo-social")
        .redimensionable()
        .frame(ancho: 90, alto: 90)
            .clipShape(Círculo())
            .shadow(radio: 3)
            .overlay(Circle().stroke(Color.rosa, lineWidth: 1))
        
        Texto("Su nombre")
            .foregroundColor(colorAzulclaro)
            .fontWeight(.semibold)
    }.padding(.leading, 10)
    
    VStack{
        Texto("10")
        .font(.system(tamaño: 30))
        .foregroundColor(lightBlueColor)
        .fontWeight(.negrita)
        
        Texto("Publicaciones")
        .font(.system(tamaño: 13))
        .foregroundColor(lightBlueColor)
    .padding(.leading, 30)
    
    VStack{
        Texto("100")
        .font(.system(tamaño: 30))
        .foregroundColor(colorazulclaro)
        .fontWeight(.negrita)
        
        Texto("Seguidores")
        .font(.system(tamaño: 13))
        .foregroundColor(lightBlueColor)
    }.padding()
    
    VStack{
        Texto("1000")
        .font(.system(tamaño: 30))
        .foregroundColor(azul claro)
        .fontWeight(.negrita)
        
        Texto("Siguiendo")
        .font(.system(tamaño: 13))
        .foregroundColor(lightBlueColor)
    }
    
}.frame(altura: 100)
.padding(.leading, 10)

Y nuestro código completo sería

struct PerfilVista: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                        .fontWeight(.semibold)
                        .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Espaciador()
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                    
                .frame(altura: 50)
                .padding(.leading, 10)
                
                HStack{
                    VStack{
                        Imagen("logo-social")
                        .redimensionable()
                        .frame(anchura: 90, altura: 90)
                            .clipShape(Círculo())
                            .shadow(radio: 3)
                            .overlay(Circle().stroke(Color.rosa, lineWidth: 1))
                        
                        Texto("Su nombre")
                            .foregroundColor(colorAzulclaro)
                            .fontWeight(.semibold)
                    }.padding(.leading, 10)
                    
                    VStack{
                        Texto("10")
                        .font(.system(tamaño: 30))
                        .foregroundColor(lightBlueColor)
                        .fontWeight(.negrita)
                        
                        Texto("Publicaciones")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    .padding(.leading, 30)
                    
                    VStack{
                        Texto("100")
                        .font(.system(tamaño: 30))
                        .foregroundColor(colorazulclaro)
                        .fontWeight(.negrita)
                        
                        Texto("Seguidores")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }.padding()
                    
                    VStack{
                        Texto("1000")
                        .font(.system(tamaño: 30))
                        .foregroundColor(azul claro)
                        .fontWeight(.negrita)
                        
                        Texto("Siguiendo")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }
                    
                }.frame(altura: 100)
                .padding(.leading, 10)
            }
        }
    }
}

Así que nuestra vista tendrá este aspecto:

screen-shot-2019-09-16-at-12-06-17

¡Genial!

Añadiendo nuestro Botón Editar Perfil y el Divisor

Uno estaría tentado a pensar que el botón Editar Perfil y el Divisor debajo de él deberían estar en un VStack:

screen-shot-2019-09-16-at-13-29-27

Pero eso no es realmente necesario ya que toda nuestra Vista está dentro de nuestro VStack principal, así que podemos simplemente añadirlos a nuestro código:

 Button(acción: {}){
    Texto("Editar Perfil")
    .fontWeight(.bold)
    .foregroundColor(lightBlueColor)
}.frame(anchura: 400)
.padding()

Separador()

que quedaría así

struct PerfilVista: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .leading){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                        .fontWeight(.semibold)
                        .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Espaciador()
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                    
                .frame(altura: 50)
                .padding(.leading, 10)
                
                HStack{
                    VStack{
                        Imagen("logo-social")
                        .redimensionable()
                        .frame(anchura: 90, altura: 90)
                            .clipShape(Círculo())
                            .shadow(radio: 3)
                            .overlay(Circle().stroke(Color.rosa, lineWidth: 1))
                        
                        Texto("Su nombre")
                            .foregroundColor(colorAzulclaro)
                            .fontWeight(.semibold)
                    }.padding(.leading, 10)
                    
                    VStack{
                        Texto("10")
                        .font(.system(tamaño: 30))
                        .foregroundColor(lightBlueColor)
                        .fontWeight(.negrita)
                        
                        Texto("Publicaciones")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    .padding(.leading, 30)
                    
                    VStack{
                        Texto("100")
                        .font(.system(tamaño: 30))
                        .foregroundColor(colorazulclaro)
                        .fontWeight(.negrita)
                        
                        Texto("Seguidores")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }.padding()
                    
                    VStack{
                        Texto("1000")
                        .font(.system(tamaño: 30))
                        .foregroundColor(azul claro)
                        .fontWeight(.negrita)
                        
                        Texto("Siguiendo")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }
                    
                }.frame(altura: 100)
                .padding(.leading, 10)
                
                Botón(acción: {}){
                    Texto("Editar perfil")
                    .fontWeight(.negrita)
                    .foregroundColor(lightBlueColor)
                }.frame(anchura: 400)
                .padding()
                
                .divisor()
            }
        }
    }
}

y nuestra UI:

screen-shot-2019-09-16-at-13-34-15

Simulando nuestra línea de tiempo

Nuestra vista de línea de tiempo se utilizará en otras partes de la aplicación, así que tiene sentido dividirla en un archivo diferente.
Podría ser reutilizado desde dentro de nuestro ProfileView igual, pero mantiene las cosas más organizadas cuando dividimos el código.

Crear un archivo TimelineView.swift.

Hay muchas maneras diferentes de mostrar datos en SwiftUI, pero elegí esta para mi aplicación:

  • Nuestra vista Timeline es un VStack de LineViews
  • Cada LineView es un HStack compuesto por 3 PreviewViews
  • Cada PreviewView tiene una imagen

screen-shot-2019-09-16-at-13-29-27-copy-2

Lo primero que voy a hacer es crear una estructura que contenga nuestros datos. Llamaré a esa estructura Preview y tendrá 2 parámetros: un id (tipo Int) para iterar y un imageURL (tipo String) que contendrá la URL de la imagen que pasaré:

struct Vista Previa {
    var id: Int
    let imageUrl: String
}

Como he dicho, podrías elegir otra forma de mostrar tus datos, pero esto me ha parecido muy fácil de entender, así que vamos a añadir primero la estructura para nuestro PreviewView.
Nuestro struct tiene una propiedad Preview que estableceré más adelante, pero usará la propiedad imageURL para renderizar la imagen:

struct VistaPrevia: View {
    let vista previa: Preview
    
    var body: alguna Vista {
        Imagen(vista previa.imageUrl)
        .redimensionable()
        .frame(anchura: 136, altura: 136)
    }
}

Con eso hecho, podemos añadir la estructura para nuestro LineView, que recibe un array de 3 Previews para mostrar en la linea.
Cambiaré esto en el futuro para reflejar datos reales, pero por ahora, estará bien:

struct LineView: View {
    let previewArray:[Preview]
    
    var body: some View {
        HStack(espaciado: 2){
            VistaPrevia(vistaPrevia: vistaPreviaArray[0])
            VistaPrevia(vistaPrevia: vistaPreviaArray[1])
            VistaPrevia(vistaPrevia: vistaPreviaArray[2])
        }
    }
}

Finalmente, podemos crear un Array de objetos Preview que recorreremos en bucle:

let vistas previas:[Vista previa] = [
    Vista previa(id: 0, imageUrl: "1"),
    Vista previa(id: 1, imageUrl: "2"),
    Vista previa(id: 2, imageUrl: "3"),
    Vista previa(id: 3, imageUrl: "4"),
    Vista previa(id: 4, imageUrl: "5"),
    Vista previa(id: 5, imageUrl: "6"),
    Vista previa(id: 6, imageUrl: "7"),
    Vista previa(id: 7, imageUrl: "8"),
    Vista previa(id: 8, imageUrl: "9"),
    Vista previa(id: 9, imageUrl: "10"),
    Vista previa(id: 10, imageUrl: "11"),
    Vista previa(id: 11, imageUrl: "12"),
    Vista previa(id: 12, imageUrl: "13")
]

Este Array tiene 13 objetos y he referenciado las imágenes que voy a utilizar con nombres del 1 al 13. También guardé esas imágenes en mi carpeta Assets, pero de nuevo, voy a cambiar eso en el futuro:

screen-shot-2019-09-16-at-14-06-55

Ahora que tenemos todo hecho, podemos iterar a través de nuestra matriz y crear nuestra LinePreviews pasando 3 objetos de vista previa a la misma.
Observe que estoy pasando el mismo objeto, pero una vez más, esto es temporal para la visualización y será cambiado:

var body: some View {
        ScrollView{
            VStack(alineación: .leading, espaciado: 2){
                ForEach(vistas previas, id: \.id) { vista previa en
                    LineView(vista previaArray: [vista previa, vista previa, vista previa])
                }
            }
        }
}

Así que nuestro código completo sería algo como esto

struct TimelineView: Vista {
    
    let vistas previas:[Vista previa] = [
        Vista previa(id: 0, imageUrl: "1"),
        Vista previa(id: 1, imageUrl: "2"),
        Vista previa(id: 2, imageUrl: "3"),
        Vista previa(id: 3, imageUrl: "4"),
        Vista previa(id: 4, imageUrl: "5"),
        Vista previa(id: 5, imageUrl: "6"),
        Vista previa(id: 6, imageUrl: "7"),
        Vista previa(id: 7, imageUrl: "8"),
        Vista previa(id: 8, imageUrl: "9"),
        Vista previa(id: 9, imageUrl: "10"),
        Vista previa(id: 10, imageUrl: "11"),
        Vista previa(id: 11, imageUrl: "12"),
        Vista previa(id: 12, imageUrl: "13")
    ]
    
    var body: some View {
            ScrollView{
                VStack(alineación: .leading, espaciado: 2){
                    ForEach(vistas previas, id: \.id) { vista previa en
                        LineView(vista previaArray: [vista previa, vista previa, vista previa])
                    }
                }
            }
    }
}

struct TimelineView_Previews: PreviewProvider {
    static var previews: some Vista {
        TimelineView()
    }
}

struct Vista Previa {
    var id: Int
    deje imageUrl: String
}

struct LineView: View {
    let vista previaArray:[Vista previa]
    
    var body: some View {
        HStack(espaciado: 2){
            VistaPrevia(vistaPrevia: vistaPreviaArray[0])
            VistaPrevia(vistaPrevia: vistaPreviaArray[1])
            VistaPrevia(vistaPrevia: vistaPreviaArray[2])
        }
    }
}

struct VistaPrevia: Vista {
    
    dejar vista previa: Vista previa
    
    var body: alguna Vista {
        Imagen(vista previa.imageUrl)
        .redimensionable()
        .frame(anchura: 136, altura: 136)
    }
}

Y si lo llamamos desde nuestro ProfileView.swift justo debajo de nuestro Divider:

...
 Button(acción: {}){
    Texto("Editar Perfil")
    .fontWeight(.bold)
    .foregroundColor(lightBlueColor)
}.frame(anchura: 400)
.padding()

Separador()

TimelineView().padding(.leading, 10)

...

También podemos añadir otro Divider justo debajo para tener casi el resultado final que queremos:

...
 Botón(acción: {}){
    Texto("Editar Perfil")
    .fontWeight(.bold)
    .foregroundColor(lightBlueColor)
}.frame(anchura: 400)
.padding()

Separador()

TimelineView().padding(.leading, 10)

Divisor()

...

¿Cómo queda?

screen-shot-2019-09-16-at-14-13-10

¿Ya se ve bien?

Vamos a terminarlo añadiendo nuestro…

Vista inferior

La vista inferior será otro archivo más, ya que la usaremos en múltiples partes de la aplicación.

Crea tu archivo BottomView.swift y en él crea un HStack (ya que los botones estarán uno al lado del otro) de 4 botones con Spacers entre ellos. ¡No olvides los iconos!

struct BottomView: View {
    var body: some View {
        HStack{
             Botón(acción: {}){
                 Imagen("home")
                 .redimensionable()
                 .frame(anchura: 30, altura: 30)
             }.padding()
             
             Espaciador()
             
             Botón(acción: {}){
                 Imagen("buscar")
                 .redimensionable()
                 .frame(anchura: 30, altura: 30)
             }.padding()
             
             Espaciador()
             
             Botón(acción: {}){
                 Imagen("botón plus")
                 .redimensionable()
                 .frame(anchura: 30, altura: 30)
             }.padding()
             
             Espaciador()
             
             Botón(acción: {}){
                 Imagen("corazón")
                 .redimensionable()
                 .frame(anchura: 30, altura: 30)
             }.padding()
             
             Espaciador()
             
             Botón(acción: {}){
                 Imagen("usuario")
                 .redimensionable()
                 .frame(anchura: 30, altura: 30)
             }.padding()
        .frame(altura: 35)
    }
}

¡Esto fue fácil! Integrémoslo en nuestro ProfileView.swift, justo debajo de nuestro último Divider:

...
Divider()
                
TimelineView().padding(.leading, 10)
                
Divisor()
                
VistaInferior()
...

Así que nuestro código completo de ProfileView sería

import SwiftUI

struct VistaPerfil: View {
    var body: some View {
        GeometryReader { geometría en
            VStack(alineación: .principal){
                HStack{
                    Texto("nombredeusuario")
                    .foregroundColor(lightBlueColor)
                        .fontWeight(.semibold)
                        .padding(.leading, 10)
                    
                    Botón(acción: {}){
                        Imagen("flecha-abajo")
                        .redimensionable()
                        .frame(anchura: 10, altura: 10)
                    }
                    .padding(.top, 5)
                    
                    Espaciador()
                    
                    Botón(acción: {}){
                        Imagen("menú")
                        .redimensionable()
                        .frame(anchura: 20, altura: 20)
                    }.padding()
                    
                .frame(altura: 50)
                .padding(.leading, 10)
                
                HStack{
                    VStack{
                        Imagen("logo-social")
                        .redimensionable()
                        .frame(anchura: 90, altura: 90)
                            .clipShape(Círculo())
                            .shadow(radio: 3)
                            .overlay(Circle().stroke(Color.rosa, lineWidth: 1))
                        
                        Texto("Su nombre")
                            .foregroundColor(colorAzulclaro)
                            .fontWeight(.semibold)
                    }.padding(.leading, 10)
                    
                    VStack{
                        Texto("10")
                        .font(.system(tamaño: 30))
                        .foregroundColor(lightBlueColor)
                        .fontWeight(.negrita)
                        
                        Texto("Publicaciones")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    .padding(.leading, 30)
                    
                    VStack{
                        Texto("100")
                        .font(.system(tamaño: 30))
                        .foregroundColor(colorazulclaro)
                        .fontWeight(.negrita)
                        
                        Texto("Seguidores")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }.padding()
                    
                    VStack{
                        Texto("1000")
                        .font(.system(tamaño: 30))
                        .foregroundColor(azul claro)
                        .fontWeight(.negrita)
                        
                        Texto("Siguiendo")
                        .font(.system(tamaño: 13))
                        .foregroundColor(lightBlueColor)
                    }
                    
                }.frame(altura: 100)
                .padding(.leading, 10)
                
                Botón(acción: {}){
                    Texto("Editar perfil")
                    .fontWeight(.negrita)
                    .foregroundColor(lightBlueColor)
                }.frame(anchura: 400)
                .padding()
                
                Separador()
                
                TimelineView().padding(.leading, 10)
                
                Divisor()
                
                Vista inferior()
            }
        }
    }
}

struct VistaPerfil_VistasPrevias: PreviewProvider {
    static var previews: some Vista {
        VistaPerfil()
    }
}

Y finalmente…

Tenemos nuestro ProfileView completo:

screen-shot-2019-09-16-at-10-08-35

¡Qué increíble!

Conclusión

Hoy has aprendido a simular una vista de perfil en tu aplicación. Todavía es sólo un simulacro, pero le daremos algo de funcionalidad con el tiempo.

Has aprendido cómo crear y reutilizar componentes en SwiftUI y cómo utilizarlos para crear una vista compleja. ¡Impresionante!

¡Vamos a crear algunas otras vistas en el próximo artículo!

¡Estate atento!

Referencia

Regístrate ahora en Back4App y empieza a construir tu Instagram Clone App.

¿Cuál es el punto positivo de SwiftUI?

Si buscas crear clones como la aplicación de Instagram, SwiftUI te ayudará.

– Facilita la creación de interfaces complejas.
– Reutilización de componentes.
– El proceso para reutilizar interfaces es simple y sencillo.

Solo necesitas los conocimientos necesarios para reutilizar esos componentes juntos.

¿Qué es Hstack, Vstack y Zstack?

Estos nombres están relacionados debido a su representación en EE. UU. SwiftUI construye sus interfaces de usuario con los siguientes patrones:

– La interfaz de usuario se construye verticalmente mediante pila vertical.
– Se construye horizontalmente mediante pila horizontal.
– Las vistas superpuestas se construyen con ZStack.

¿Cuál es la mejor característica de SwiftUI?

La mejor característica de SwiftUI es su reutilización. Puedes reutilizar los componentes una y otra vez para crear las vistas. Esto aplica a todas las aplicaciones. Necesitas saber cómo usar estos componentes.


Leave a reply

Your email address will not be published.