Si en el placeholder ([email protected]) no te agarra el color puedes hacer esto:
Text(verbatim: "[email protected]").font(.caption).foregroundColor(.gray)
Introducción al curso
Construyamos una app para iOS
Introducción a la arquitectura MVVM
Planeando nuestra app
Creando las primeras pantallas de la app
Programando la primera pantalla en módulos
Escribiendo la lógica para mostrar dos pantallas
Pantalla de inicio de sesión con SecureField y Scroll
Completando nuestra pantalla de inicio de sesión
Pantalla de registro de usuario
Comprobando el funcionamiento de nuestras pantallas
Estructura de las pantallas con TabView
Creando nuestra pantalla home
Pantalla home: logo y barra de búsqueda
Pantalla home: programación de interfaces estáticas
Pantalla home: carruseles
Aplicando arquitectura MVVM
Creando estructura para arquitectura MVVM
Modelando nuestro JSON
Peticiones al servidor
Mostrar información de un servidor de manera dinámica
Mostrar imágenes de forma dinámica y eficiente con LazyVGrid
Reproductor y búsqueda de video
Pasar datos entre pantallas
Darle datos de inicio a un Canvas
Reproducir videos dinámicamente de un servidor
Mostrar imágenes dinámicamente de un servidor
Mostrar alertas
Programar clase de búsqueda
Programar método de búsqueda
Últimas pantallas de la app
Pantalla de favoritos
Pantalla de perfil de usuario
Módulo de ajustes de perfil con Toggle
Pantalla de edición de perfil
Módulo de edición de perfil
Guardado interno de datos
Utilizando la cámara y fotos del iPhone
Captura de foto de perfil: ImagePicker y vista Sheet
Captura de foto de perfil con la cámara: modificar librerías de terceros
Captura de foto de perfil con la cámara: recuperar imágenes guardadas
¿Qué más posibilidades tiene SwiftUI?
Mejoremos nuestra app
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Juan Villalvazo
Aportes 14
Preguntas 1
Si en el placeholder ([email protected]) no te agarra el color puedes hacer esto:
Text(verbatim: "[email protected]").font(.caption).foregroundColor(.gray)
En la sección de los botones Iniciar Sesión y Regístrate, yo preferí quitar los Spacer a lado y lado de los botones y mejor poner un padding horizontal de 30 al contenedor HStack. Igual que hicimos con el VStack de InicioSesionView.
De esta forma queda más parecido al diseño original, no tan apretado todo el contenido.
(
Yo recomiendo para los placeholders crear una extensión de View y agregar el metodo placeholder
extension View {
func placeholder<Content: View>(
when shouldShow: Bool,
alignment: Alignment = .leading,
@ViewBuilder placeholder: () -> Content) -> some View {
ZStack(alignment: alignment) {
placeholder().opacity(shouldShow ? 1 : 0)
self
}
}
}
Que luego podemos utilizar de esta manera, para que quede el código más limpio y más legible
TextField("", text: $email).placeholder(when: email.isEmpty) {
Text("[email protected]").font(.caption).foregroundColor(.gray)
}
Cuando un color va ser igual tanto para el modo light como para el modo dark, puedes colocar en el inspector en la parte de Appearances en un valor “None”
Hice este componente para reutilizar los estilos de los inputs de esta pantalla:
struct GameStreamAuthInput<Content: View>: View {
let input: () -> Content
let title: String
let placeholderText: String
let showPlaceholder: Bool
init(
title: String,
placeholderText: String,
showPlaceholder: Bool,
aligment: Alignment = .leading,
input: @escaping () -> Content
) {
self.input = input
self.title = title
self.placeholderText = placeholderText
self.showPlaceholder = showPlaceholder
}
var body: some View {
Text(title)
.foregroundColor(Color("dark_cyan"))
ZStack(alignment: .leading){
input().placeholder(
when: self.showPlaceholder
) {
Text(self.placeholderText)
.font(.caption)
.foregroundColor(.gray)
}
}
Divider()
.frame(height: 1)
.background(Color("dark_cyan"))
.padding(.bottom)
}
}
Y en la pantalla de log in:
GameStreamAuthInput(
title: "Correo electrónico",
placeholderText: "[email protected]",
showPlaceholder: email.isEmpty
) {
TextField(
"",
text: $email
)
}
GameStreamAuthInput(
title: "Contraseña",
placeholderText: "********",
showPlaceholder: password.isEmpty
) {
SecureField(
"",
text: $password
)
}
Para Swift 14 creo que la forma correcta de agregar un placeholder custom sería esto:
TextField(
text: $yourProperty,
label: {
Text(“your label value”).foregroundColor(your color)
})
Esto evita usar un ZStack
Yo le agregué el toggle para quitar el máscara de la contraseña. No es el código más lindo pero es trabajo honesto xD
@State var correo = ""
@State var contrasena = ""
@State var isSecured: Bool = true
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Correo electrónico").bold().foregroundColor(Color(red: 0.25, green: 0.79, blue: 0.63, opacity: 1.0))
ZStack(alignment: .leading) {
if correo.isEmpty {
Text(verbatim: "[email protected]").font(.caption).foregroundColor(.gray)
}
TextField("", text: $correo).foregroundColor(.white)
}
Divider().frame(height: 1).background(Color(red: 0.25, green: 0.79, blue: 0.63, opacity: 1.0)).padding(.bottom)
HStack() {
ZStack(alignment: .leading) {
Group {
if isSecured{
if contrasena.isEmpty {
Text(verbatim: "Escribe tu contraseña").font(.caption).foregroundColor(.gray)
}
SecureField("", text: $contrasena).foregroundColor(.white)
} else {
TextField("", text: $contrasena).foregroundColor(.white)
}
}
}
Button(action: {
isSecured.toggle()
}) {
Image(systemName: self.isSecured ? "eye.slash" : "eye")
.accentColor(.gray)
}
}
Divider().frame(height: 1).background(Color(red: 0.25, green: 0.79, blue: 0.63, opacity: 1.0)).padding(.bottom)
}.padding(.horizontal, 80)
}
}
}
Y aquí se ve funcionando:
Contraseña súper segura :v
Yo decidí usar TextFields y separar cada campo del formulario en un componente Form:
struct Login: View {
@State var email = String()
@State var password = String()
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Form(label: "Correo electrónico", placeholder: "[email protected]", value: $email)
Divider()
.frame(height: 1)
Form(label: "Contraseña", placeholder: "4%C5Pj*^6*&8", value: $password)
}
}
// .background(Color("background"))
}
}
struct Form: View {
let label: String
let placeholder: String
var value: Binding<String> // para leer el valor usar la propiedad .wrappedValue
var body: some View {
Text(label)
.foregroundStyle(Color("darkcyan"))
.bold()
TextField(text: value) {
Text(placeholder)
.foregroundColor(.gray)
}
.foregroundColor(.white)
.bold()
Divider()
.frame(height: 1)
.background(Color("darkcyan"))
}
}
Como complemento a la extencion aportada por Omar, yo crearia otra extencion de View para implementar el TextField completo
extension View {
func customize(
when shouldShow: Bool,
hint: String,
title: String) -> some View {
VStack(alignment: .leading){
Text(title).foregroundColor(Color("dark-cyan")).padding(.bottom, -4.0)
ZStack(alignment: .leading){
Text(hint)
.font(.caption)
.foregroundColor(.gray)
.opacity(shouldShow ? 1 : 0)
.padding(.leading, 4.0)
self
}
Divider().frame(height:1).background(Color("dark-cyan"))
}
}
}
Y se utlizaria desde asi:
<code>
TextField("", text: $email).customize(when: email.isEmpty, hint: "julianmp0", title: "Correo Electrónico")
les ahorro todo el parrafo de codigo para hacer el textfield con placeholder
TextField("", text: $correo, prompt: Text(verbatim:"[email protected]").foregroundColor(Color(white:0.7).foregroundColor(.white).tint(Color("Dark-Cyan"))
basicamente el prompt permite cambiar el placeholder pasando un text pueden hacer los cambios que requieran
el verbatim evita que iOS detecte links y lo tome como string literal
y el tint es para cambiar el color del cursor, ya que siempre lo muestra azul y no cuadra con el tema de la aplicacion, asi que lo deje en dark cyan
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?