项目背景

闲来无事,在使用某云音乐听歌的时候发现一个侧滑展开的内页,交互效果还不错。

那么这一章节中,我们将使用​​SwiftUI​​搭建一个侧边展开页面交互。

项目搭建

首先,创建一个新的​​SwiftUI​​​项目,命名为​​SlideOutMenu​​。

展开&收起,使用SwiftUI搭建一个侧滑展开页面交互_偏移量

逻辑分析

首先我们来分析下基本的逻辑,一般的侧滑展开方式的交互是,在首页右上角有一个“更多”的按钮,点击按钮时,内页菜单从左往右划出,滑出至离右边20~30的位置停止。

然后首页背景将蒙上一个蒙层,点击蒙层时,侧滑展开的页面从右往左收起

简单分析完逻辑后,我们来实现这个交互。

首页入口

首先,我们需要在首页搭建一个入口,示例:

// 顶部导航入口
private var moreBtnView: some View {
Button(action: {
}) {
Image(systemName: "list.bullet")
.foregroundColor(.black)
}
}

然后,我们可以使用​​NavigationView​​​和​​navigationBarItems​​创建顶部导航按钮样式,示例:

var body: some View {
NavigationView {
Text("点击左上角侧滑展开")
.padding()
.navigationBarTitle("首页", displayMode: .inline)
.navigationBarItems(leading: moreBtnView)
}
}

展开&收起,使用SwiftUI搭建一个侧滑展开页面交互_Swift_02

如此,首页入口部分我们就完成了。

左边菜单

接下来,我们来构建左侧菜单的内容。我们可以沿用之前设计过的“设置”页面的结构,我们先来构建栏目结构。示例:

// MARK: 栏目结构
struct listItemView: View {
var itemImage: String
var itemName: String
var body: some View {
Button(action: {
}) {
HStack {
Image(systemName: itemImage)
.font(.system(size: 17))
.foregroundColor(.black)
Text(itemName)
.foregroundColor(.black)
.font(.system(size: 17))
Spacer()
Image(systemName: "chevron.forward")
.font(.system(size: 14))
.foregroundColor(.gray)
}.padding(.vertical, 10)
}
}
}

在我们构建侧滑展开的页面前,我们需要声明两个变量,一个是侧滑展开的页面的宽度,一个是当前这个页面的位置。示例:

@State var menuWidth = UIScreen.main.bounds.width - 60
@State var offsetX = -UIScreen.main.bounds.width + 60

我们设置的侧滑展开页面的宽度是​​屏幕宽度-60​​​,而当前侧滑展开页面的位置是​​负位置​​,这样就可以在展示的时候先把页面隐藏起来

而当我们点击顶部导航中的“更多”按钮时,将​​offsetX​​偏移量X轴坐标设置为​​0​​。示例:

// 顶部导航入口
private var moreBtnView: some View {
Button(action: {
withAnimation {
offsetX = 0
}
}) {
Image(systemName: "list.bullet")
.foregroundColor(.black)
}
}

然后,我们创建一个新视图来构建侧滑展开的页面内容,示例:

// MARK: 左侧菜单
struct SlideOutMenu: View {
@Binding var menuWidth: CGFloat
@Binding var offsetX: CGFloat

var body: some View {
Form {
Section {
}
Section {
listItemView(itemImage: "lock", itemName: "账号绑定")
listItemView(itemImage: "gear.circle", itemName: "通用设置")
listItemView(itemImage: "briefcase", itemName: "简历管理")
}
Section {
listItemView(itemImage: "icloud.and.arrow.down", itemName: "版本更新")
listItemView(itemImage: "leaf", itemName: "清理缓存")
listItemView(itemImage: "person", itemName: "关于掘金")
}
}
.padding(.trailing, UIScreen.main.bounds.width - menuWidth)
.edgesIgnoringSafeArea(.all)
.shadow(color: Color.black.opacity(offsetX != 0 ? 0.1 : 0), radius: 5, x: 5, y: 0)
.offset(x: offsetX)
.background(
Color.black.opacity(offsetX == 0 ? 0.5 : 0)
.ignoresSafeArea(.all, edges: .vertical)
.onTapGesture {
withAnimation {
offsetX = -menuWidth

上述代码中,我们也对页面宽度​​menuWidth​​​、偏移位置​​offsetX​​​进行了声明,方便之后我们在​​ContentView​​视图中进行双向绑定

我么使用​​Form​​​表单和​​Section​​段落构建样式,这点就不说了。

值得说的一点是,我们设置了在页面展开的时候,也就是​​offsetX​​​页面偏移量​​X轴坐标不为0​​,我们加了一个阴影,完善了侧滑展开页面的悬浮效果

然后使用​​offset​​​调整页面初始位置。背景部分,除了根据​​offsetX​​页面偏移量X轴坐标加了一个蒙层,而且当我们点击的背景的时候,我们将偏移位置​​offsetX​​重新赋值,这样就能实现收起的交互效果。

我们在​​ContentView​​视图中展示侧滑展开视图,示例:

var body: some View {
ZStack {
NavigationView {
Text("点击左上角侧滑展开")
.padding()
.navigationBarTitle("首页", displayMode: .inline)
.navigationBarItems(leading: moreBtnView)
}
SlideOutMenu(menuWidth: $menuWidth, offsetX: $offsetX)
}
}

项目展示

展开&收起,使用SwiftUI搭建一个侧滑展开页面交互_左侧菜单_03

恭喜你,完成了本章的全部内容!

快来动手试试吧。

如果本专栏对你有帮助,不妨点赞、评论、关注~