En este capítulo, aprenderá a utilizar MatchedGeometryEffect
para crear un menú de navegación.
En el proceso de construcción de SwiftUI
una aplicación, a menudo usamos TabView
el menú inferior para construir, pero más a menudo necesitamos dibujar el menú inferior nosotros mismos debido a nuestras necesidades personalizadas.
Entonces, en este capítulo, intentemos construir un menú de navegación inferior .
Proyecto de construcción
Primero, crea un nuevo SwiftUI
proyecto llamado NavigationMenu
.
edificio de estilo
Primero construyamos la parte de estilo del menú de navegación , primero declaramos una matriz para almacenar el menú inferior que necesitamos usar .
let menuItems = ["首页", "发现", "关注", "我的"]
复制代码
Luego, creamos el estilo del menú de navegación usando ForEach
bucles y texto, ejemplo:Text
HStack {
ForEach(menuItems.indices,id: \.self) { index in
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.background(Capsule().foregroundColor(Color.blue))
.foregroundColor(.white)
}
}
复制代码
En el código anterior, creamos 4 menús de navegaciónForEach
usando bucles y texto , y configuramos el color de relleno de fondo en azul y el texto en blanco.Text
interacción de cambio de menú
El efecto es bueno, luego agregamos un estado al menú de navegación , y cuando hacemos clic en el menú , cambiamos la selección . Ejemplo:
@State var selectedItem = 0
复制代码
Luego, de acuerdo con el estado seleccionado , cambie el color del menú de navegación para lograr el efecto de hacer clic y cambiar. Ejemplo:
if index == selectedItem {
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.background(Capsule().foregroundColor(Color.blue))
.foregroundColor(.white)
} else {
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.background(Capsule().foregroundColor(Color(.systemGray6)))
.foregroundColor(.black)
.onTapGesture {
selectedItem = index
}
}
复制代码
index
En el código anterior, juzgamos el estado de selección del menú actual por el índice del menú actual .
当菜单处于选中时,我们使用原来蓝色背景 白色字体的样式,当菜单处于未选中时,我们设置为灰色背景 黑色文字,且点击时切换当前index
为选中索引。
这样,我们就实现了导航菜单的选中切换交互。
导航切换动画
完成基础的导航菜单切换后,我们加一点“特效”,我们使用@Namespace
声明一个动画变量Transition
。示例:
@Namespace private var Transition
复制代码
然后我们给导航菜单选中的状态样式加一个过渡动画。示例:
.matchedGeometryEffect(id: "menuItem", in: Transition)
复制代码
上述代码中,id
和namespace
可以标识哪些视图属于转场动画 Transition
。同时还需要在点击进行状态切换的时候启用动画效果。示例:
.onTapGesture {
withAnimation(.easeOut) {
selectedItem = index
}
}
复制代码
最后,我们在调整下位置,看看最终效果。
导航菜单进阶
文字导航已经完成了,在常用的App中会使用图片+文字的形式构建底部导航菜单,我们这边也试试。
首先先定义好使用的图标数组,示例:
let menuImages = ["house", "paperplane", "heart", "person.2"]
复制代码
由于文字和图标是纵向排列,我们使用VStack
构建页面,示例:
选中部分
VStack {
Image(systemName: menuImages[index]+".fill")
.foregroundColor(Color.blue)
.font(.system(size: 24))
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.foregroundColor(.blue)
}
复制代码
上述代码中,我们在VStack
纵向视图中使用Image
图标和Text
文字构架了选中的样式,图标部分使用图标+fill
修饰符变为填充样式,同时图标颜色设置为蓝色。文字部分,我们把文字颜色修改为蓝色作为选中颜色。
非选中部分
VStack {
Image(systemName: menuImages[index])
.foregroundColor(Color(.systemGray4))
.font(.system(size: 24))
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.foregroundColor(Color(.systemGray4))
}
复制代码
对于非选中部分,我们也同样处理,只是把颜色变成了灰色。
最后将.matchedGeometryEffect
修饰符和.onTapGesture
调整为VStack
视图外,预览看下效果:
这样,我们就完成了一个图标加文字的底部导航菜单。
导航菜单背景
当我们给整个视图填充一个背景颜色时,我们发现出了点问题。由于我们底部导航菜单并没有背景颜色,导致在白色背景下看起来还不错,但其他背景颜色下就会和背景颜色融为一体,这不是我们想要的结果。
我们尝试加一个圆角白色的背景作为底部菜单的显示区域看看。示例:
.padding(.horizontal,30)
.padding(.top,10)
.padding(.bottom,10)
.background(Color.white)
.cornerRadius(60)
.overlay(RoundedRectangle(cornerRadius: 60) .stroke(Color(red: 220/255, green: 223/255, blue: 230/255), lineWidth: 1))
复制代码
En el código anterior, aumentamos los márgenes del menú inferior, izquierdo y derecho , y luego establecemos el color de fondo en blanco y las esquinas redondeadas en 60 .
Para poder ver el área de visualización de la navegación inferior incluso en el fondo de vista blanco, usamos un overlay
modificador para agregar un borde al menú inferior . Volvamos al fondo de vista blanco para ver el efecto:
¡Se ve bien!
Por supuesto, hay otros estilos del menú de navegación inferior. Puede intentar convertir toda el área del menú inferior en blanco , que es el método más utilizado para configurar el fondo del menú inferior. También puede agregar un fondo borroso y transparente . Efecto sobre la base de blanco , similar a algún software social. Práctica común, etc.
Código para este capítulo
import SwiftUI
struct ContentView: View {
let menuItems = ["首页", "发现", "关注", "我的"]
let menuImages = ["house", "paperplane", "heart", "person.2"]
@State var selectedItem = 0
@Namespace private var Transition
var body: some View {
ZStack {
Color.white
.ignoresSafeArea()
VStack {
Spacer()
HStack {
ForEach(menuItems.indices, id: \.self) { index in
if index == selectedItem {
VStack {
Image(systemName: menuImages[index]+".fill")
.foregroundColor(Color.blue)
.font(.system(size: 24))
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.foregroundColor(.blue)
}.matchedGeometryEffect(id: "menuItem", in: Transition)
} else {
VStack {
Image(systemName: menuImages[index])
.foregroundColor(Color(.systemGray4))
.font(.system(size: 24))
Text(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.foregroundColor(Color(.systemGray4))
}
.onTapGesture {
withAnimation(.easeOut) {
selectedItem = index
}
}
}
}
}
.padding(.horizontal,30)
.padding(.top,10)
.padding(.bottom,10)
.background(Color.white)
.cornerRadius(60)
.overlay(RoundedRectangle(cornerRadius: 60) .stroke(Color(red: 220/255, green: 223/255, blue: 230/255), lineWidth: 1))
}
}
}
}
复制代码
¡Felicitaciones, ha completado todo en este capítulo!
¡Ven y pruébalo!
Si esta columna es útil para usted, haga clic en Me gusta, comente y siga ~
Estoy participando en el reclutamiento del programa de firma de creadores de la Comunidad Tecnológica de Nuggets, haga clic en el enlace para registrarse y enviar .