Saltar al contenido principal
Be Native Be Native

Artículo

Crear botones personalizados en SwiftUI

Una de las funciones clave de SwiftUI es permitir crear componentes personalizados. En este tutorial vamos a aprender a cómo crear botones personalizados en estilo para nuestra app.

María Soriano · · 3 min de lectura

Lee el artículo o escúchalo como podcast en la app. Descarga Be Native ahora.

Descarga Be Native en el App StoreDescarga Be Native en el Mac App Store

Cuando queremos desarrollar aplicaciones con SwiftUI, la reutilización de componentes es clave para tener un código limpio, bien estructurado, eficiente y fácil de mantener. A continuación vamos a ver un ejemplo de creación de un componente reutilizable, un botón personalizado que podremos incorporar a diferentes vistas en nuestra aplicación.

Componentes reutilizables en SwiftUI

SwiftUI facilita el uso de componentes que pueden ser reutilizados en diferentes partes o vistas de nuestra aplicación. Por un lado, esto reduce la duplicación del código. Por otro lado, facilita el mantenimiento y la escalabilidad de nuestras aplicaciones o proyectos.

Beneficios de utilizar componentes reutilizables en nuestras aplicaciones

  • Eficiencia: Ahorra tiempo al evitar tener que volver a reescribir código que puede ser idéntico o muy similar.
  • Consistencia: Mantiene una apariencia y un comportamiento uniforme en toda la aplicación.
  • Mantenimiento: Facilita el proceso de mejora o actualización ya que todo se encuentra en un solo lugar.

Creación de un botón personalizado

Comenzamos creando un botón personalizado en un nuevo archivo Swift. A esta vista le daremos el nombre de BotonPersonalizado. Este botón tendrá un estilo específico que lo hará destacar y será fácilmente reutilizable en cualquier otra vista que lo necesite.

swift
struct BotonPersonalizado: View {
    
    var texto: String
    var accion: () -> Void
    
    var body: some View {
        Button(action: accion) {
            Text(texto)
        }
        .frame(width: 400, height: 80)
        .foregroundStyle(.blue)
        .font(.title)
        .overlay(
            Capsule().stroke(
                LinearGradient(
                    colors: [.cyan, .purple, .cyan],
                    startPoint: .leading,
                    endPoint: .trailing
                ),
                lineWidth: 5
            )
        )
    }
}

BotonPersonalizado es una estructura que conforma al protocolo View y que recibe dos parámetros: texto y accion.

  • texto es un String que mostrará el texto que aparece en el botón.
  • accion es un closure que define la acción a realizar cuando se hace clic en el botón. En este caso una "función vacía".

Como el objetivo es reutilizar el estilo del botón en diferentes pantallas de nuestra aplicación, necesitamos poder ajustar su texto y su acción según las necesidades de cada una de esas pantallas y de lo que queramos que ocurra cuando el usuario interactúe con ese botón.

Ahora solo tenemos que ir a la vista donde queremos incorporar el struct BotonPersonalizado e incorporarlo, pasando los parámetros de texto y accion como mejor nos convengan.

swift
struct BookCardView: View {
    @State private var books = Books() 
    @State private var title: String = ""
    @State private var author: String = ""
    @State private var pages: String = ""
    @State private var status: Bool = false
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Biblioteca 📚").font(.largeTitle.bold())
            
            TextField("Título del libro", text: $title) 
            TextField("Autor", text: $author) 
            TextField("Número de páginas", text: $pages) 
            
            Toggle(isOn: $status) {
                Text("Finalizado")
            }
            
            BotonPersonalizado(texto: "Añadir libro", accion: {
                books.addLibro(title: title, author: author, pages: pages, status: status)
                title = "" 
                author = "" 
                pages = "" 
                status = false
                })
            List {
                ForEach(books.bookList.indices, id: \.self) { index in
                    let book = books.bookList[index]
                    VStack {
                        HStack {
                            Text("Título:").font(.subheadline)
                            Text(book.title).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Autor:").font(.subheadline)
                            Text(book.author).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Páginas:").font(.subheadline)
                            Text(book.pages).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Estado:").font(.subheadline)
                            Text(book.status ? "Leído" : "No empezado")
                                .font(.subheadline.bold())
                        }
                    }
                }
                .onDelete(perform: { indexSet in
                    indexSet.forEach { index in
                        books.eliminarLibro(at: index)
                    }
                })
            }
            .frame(height: 200)
            .clipShape(RoundedRectangle(cornerRadius: 10))
        }
        .textFieldStyle(RoundedBorderTextFieldStyle())
        .padding()
        .background(
            LinearGradient(gradient: Gradient(colors: [Color.blue, Color.purple]), startPoint: .top, endPoint: .bottom)
                .opacity(0.4)
        )
        .clipShape(RoundedRectangle(cornerRadius: 20))
        .frame(width: 400)
    }
}

De esta forma tan sencilla, podemos reutilizar componentes en diferentes vistas de una misma aplicación sin necesidad de repetir código.