Creando UI al estilo Tinder en SwiftUI Parte I: Gradientes y Botones
Tags: swift, swiftui, mobile
Published: 2019-08-06 20:24:39

Este es mi primer post sobre desarrollo mobile, mi objetivo es mostrar cómo crear interfaces complejas, es decir, que tengan micro-interacciones, interacciones con gestos, animaciones, etc.

En esta instancia mostrare como montar la interface central de Tinder, donde vas Swipeando los rostros de los pretendientes dando like o unlike

Asumiré que tienes nociones sobre Swift y que ya sabes que es [SwiftUI](https://developer.apple.com/xcode/swiftui/), por tanto no explicare detalles del lenguaje y no profundizare sobre SwiftUI, por lo demás ya existen un montón de posts ahi afuera que desarrollan las nociones básica de este maravilloso Framework desarrollado por apple.

_________________
###Stack

**Xcode** 11.0 Beta 4 (11M374r)
**MacOS Catalina** Versión 10.15 Beta (19A512f)
**Swift** 5.0
_________________

Lo primero que haremos sera revisar nuestro prototipo y extraeremos sus colores y assets principales, los agregaremos a nuestro **Assets.xcassets** con sus correspondientes nombres.


![](https://thepracticaldev.s3.amazonaws.com/i/dy23qwtetobhtl6pgge3.png)

### Construyendo el Header

SwiftUI nos presenta una forma sencilla de trabajar con gradientes: LinearGradient, RadialGradient y AngularGradient. En esta ocasión trabajaremos con Linear gradient, que es una **struct** que nos pide un **Gradient** y dos **UnitPoint**, inicial y final.

Gradient nos pide un array de colores, que en nuestro caso sera el del gradiente izquierdo y derecho descritos anteriormente

```swift
Gradient(colors: [Color("left_gradient_color"), Color("rigth_gradient_color")])
```

Un UnitPoint es un punto, imagina un plano cartesiano con las coordenadas X y Y. Puedes inicializar asi:

```swift
UnitPoint(x: 0.0, y: 0.0)
```

Pero tambien puedes acceder a las constantes

```swift
UnitPoint.bottom
UnitPoint.bottomLeading
UnitPoint.bottomTrailing
UnitPoint.center
UnitPoint.leading
UnitPoint.top
UnitPoint.topLeading
UnitPoint.topTrailing
UnitPoint.trailing
UnitPoint.zero
```

Si quieres un Gradiente que vaya de izquierda a derecha utilizarías el **UnitPoint.leading** y el **UnitPoint.trailing**, generalmente estas constantes te servirán para la mayoría de los casos en los que quieras utilizar gradientes, sin embargo siempre podrás inicializar un **UnitPoint** con un punto arbitrario en el plano, para lograr algo exactamente como lo que estas buscando.
 
![](https://thepracticaldev.s3.amazonaws.com/i/oe7jsog1lbfsssgpx4ps.png)

```swift

import SwiftUI

struct GradientHeader: View {
    var body: some View {
          VStack{
           Text("Discover")
               .font(.system(size: 30))
               .bold()
               .foregroundColor(.white)
               .offset(x:25, y: 25)
               
          }
          .frame(minWidth:0, maxWidth: .infinity, alignment: .leading)
          .frame(height: 180)
          .background(LinearGradient(gradient: Gradient(colors: [Color("left_gradient_color"),Color("rigth_gradient_color")]), startPoint: .leading, endPoint: .trailing))
                        
    }
}

```

El resultado del código anterior nos dará como resultado lo siguiente

![](https://thepracticaldev.s3.amazonaws.com/i/qa2d7mc6ofepevi04pm2.png)

## Botones

Los botones en SwiftUI son muy simples de declarar

```swift

Button("Click Me"){
//tap action
}
.frame(width:60, height:60)

```

Otra forma de declararlo

```swift

Button(action:{
//tap action
}){
Text("Click Me")
}
.frame(width:60, height:60)

```

La forma anterior nos permite agregar mas cosas, como **Images**, **Stacks**, etc


En esta imagen mostramos la modificación de un botón con cada linea de código que agrega un nuevo modificador a la vista.

![](https://thepracticaldev.s3.amazonaws.com/i/pzv2o0uswyxqaggtndhn.png)


```swift

Button("Click Me"){
//tap action
}
.frame(width:60, height:60)
.background(Color.white)
.mask(Circle())
.shadow(color: Color("Shadow"), radius: 4, x: 0, y: 5)

```

Una forma más avanzada de ordenar nuestros botones, es generar unos estilos derivados de ButtonStyle, así podremos inyectar estilos de manera fácil a nuestros botones solo referenciando sus respectivos nombres de estilos.

```swift
//button+styles.swift
import Foundation
import SwiftUI

public struct Rounded : ButtonStyle {
    public func body(configuration: Button<Self.Label>, isPressed: Bool) -> some View {
        configuration
            .background(Color.white)
            .mask(Circle())
            .shadow(color: Color("Shadow"), radius: 4, x: 0, y: 5)
           
    }
}

public struct Big : ButtonStyle {
    public func body(configuration: Button<Self.Label>, isPressed: Bool) -> some View {
        configuration
            .frame(width: 60, height: 60)
    }
    
}

extension StaticMember where Base : ButtonStyle {
    public static var rounded: Rounded.Member {
        StaticMember<Rounded>(Rounded())
    }
    public static var big: Big.Member {
       StaticMember<Big>(Big())
   }
}
```

Aislando nuestros estilos como se muestran anteriormente, nos queda una composición de nuestro botón de manera mas limpia, con la aventaja añadida que podemos combinar estilos, aquí podemos ver como combinamos el estilo de un botón grande con el de un botón redondeado.

```swift
//Crea un nuevo Documento SwiftUI
import SwiftUI

struct ContentView: View {
    
    var body: some View {
        Button("Click Me!"){
          //Tap Code!!   
        }
        .buttonStyle(.rounded)
        .buttonStyle(.big)
        
    }
}
```

Una vez que hemos codeado nuestro botón, crearemos una Vista que contenga todos nuestros botones, intercalando los botones pequeños y grandes como muestra nuestro prototipo, los botones de los costados tienen un pequeño desfase hacia arriba.

```swift

//Buttons.swift

import SwiftUI

struct Buttons: View {
    
    var body: some View {
        
          HStack(alignment: .center){
               
             Button(action:{}){
               Image("redo")
                 .resizable()
                 .frame(width: 22, height: 22)
                 .foregroundColor(Color("redo"))
              }
              .buttonStyle(.rounded)
              .buttonStyle(.small)
              .offset(y:-14.0)
            
              // Agregar los otros 4 botones, intercalando .small y .big 
              // solo los botones de los costados tienen offset y : -14
           }
           .padding(.bottom, 35)
           .frame(minWidth:0, maxWidth:.infinity)
    }
}
```

El resultado de generar los botones de esta manera

![](https://thepracticaldev.s3.amazonaws.com/i/qa1ehbe0i2jatn96gd7x.png)

### Conclusión


Desarrollar vistas con SwiftUI es realmente sencillo, los desarrolladores **Swift** agradecerán la forma coherente que tiene SwiftUI de utilizar la potencia del lenguaje con sus nuevas características. Una cosa interesante de observar es lo parecido con react native, a los desarrolladores que vengan de este mundo, les resultara muy familiar la forma en que se construyen las interfaces; Quizás sea una excelente oportunidad para explorar el mundo del desarrollo nativo.

Se agradece cualquier critica que puedan dejar, ademas de compartir el post con desarrolladores interesados en el desarrollo Mobile.

Anexare el proyecto de Github con los contenidos del tutorial:

[Repositorio Github](https://github.com/Transmigrado/TinderUI-SwiftUI)

[Tag con el avance de este post](https://github.com/Transmigrado/TinderUI-SwiftUI/releases/tag/v0.1)

## Happy coding!!!