携手创作,共同生长!这是我参与「日新计划 8 月更文应战」的第26天,点击查看活动详情。

项目布景

在逛某站的时分,看到一个运用HTMLl+CSS构建一个伸缩式导航栏的案例,觉得蛮有意思。

在客户端开发中,导航栏是必不可少的设计元素之一。但纵观许多国内的App,根本都是最为基础的导航栏,缺乏新意。

在本章中,咱们就试试运用SwiftUI构建一个伸缩式导航栏,作为操练。

那么,让咱们开端吧。

项目搭建

首要,创立一个新的SwiftUI项目,命名为SwiftUITabView

SwiftUI完成了伸缩式导航栏!好家伙,还不收藏一波~

缩短视图

款式设计方面,由于咱们需求构建一个伸缩式的导航栏,那么需求拆解成伸展式缩短式两种款式作用。

首要咱们需求声明一个变量来存储它的状况,示例:

@State var isFold: Bool = false

然后咱们来构建缩短时的款式,示例:

// 收起作用
func foldView() -> some View {
Image(systemName: "list.bullet")
.font(.system(size: 24))
.frame(minWidth: 0, maxWidth: 60, minHeight: 0, maxHeight: 60)
.foregroundColor(.black)
.background(.white)
.cornerRadius(30)
.onTapGesture {
   withAnimation(.spring()) {
 self.isFold.toggle()
   }
}
}

SwiftUI完成了伸缩式导航栏!好家伙,还不收藏一波~

上述代码中,咱们构建了缩短时的款式视图foldView。除了根本的视图款式外,咱们在点击这个按钮视图时,切换isFold的状况。

打开视图

然后时打开视图,打开视图部分有两部分组成,一部分是“封闭”按钮,另一块则是规范的导航栏,咱们来构建款式。

首要需求声明一个数组来标明咱们导航栏内容,示例:

let menuItems = ["主页", "沸点", "课程", "我的"]

然后再声明一个变量来表示当前选中的导航栏的栏目,示例:

@State var selectedItem = 0

最终,咱们创立一个新的视图来完成打开视图的款式部分,示例:

// 打开作用
func unfoldView() -> some View {
HStack {
Image(systemName: "xmark")
.font(.system(size: 24))
.foregroundColor(.pink)
.onTapGesture {
    withAnimation(.spring()) {  
 self.isFold.toggle()
    }
}
ForEach(menuItems.indices, id: \.self) { index in
if index == selectedItem {
Text(menuItems[index])
.font(.system(size: 17))
.padding(.horizontal, 15)
.foregroundColor(.pink)
} else {
Text(menuItems[index])
.font(.system(size: 17))
.padding(.horizontal, 15)
.foregroundColor(.black)
.onTapGesture {
selectedItem = index
}
}
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 60)
.background(.white)
.cornerRadius(30)
.padding(.horizontal)
}

SwiftUI完成了伸缩式导航栏!好家伙,还不收藏一波~

上述代码中,咱们创立了一个打开时的视图unfoldView

然后运用HStack横向视图布局,将一个按钮和导航栏文字内容并排展示,当咱们点击“封闭”按钮的时分,切换isFold的状况,以及咱们还依据当前点击的index的方位,更新selectedItem选中的栏目,当选中时,咱们给选中的栏目设置一个粉色的文字色彩用于区别。

主页视图

完成两个视图后,咱们回来ContentView视图,咱们依据isFold设置视图,示例:

var body: some View {
ZStack {
Color(.systemGray6)
if isFold {
unfoldView()
} else {
foldView()
}
}.edgesIgnoringSafeArea(.all)
}

作用还不错,只是缺少了过渡动画,整个交互看起来略显僵硬。

过渡动画

咱们先声明一个变量来存储交流方位的状况,示例:

@Namespace private var Transition

然后运用matchedGeometryEffect修饰符进行方位过渡切换,matchedGeometryEffect修饰符需求修饰两个按钮,示例:

//收起时按钮
Image(systemName: "list.bullet”)
 .matchedGeometryEffect(id: "fold", in: Transition) 
//打开时按钮
Image(systemName: "xmark”)
 .matchedGeometryEffect(id: "fold", in: Transition)

这里假如咱们要看到最终的作用,咱们需求运转模拟器,在真机环境下才能看到最终的交互作用。

项目预览

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

快来动手试试吧。

假如本专栏对你有协助,无妨点赞、评论、关注~