SwiftUI完成了伸缩式导航栏!好家伙,还不收藏一波~
项目背景
在逛某站的时候,看到一个使用HTMLl+CSS
构建一个伸缩式导航栏的案例,觉得蛮有意思。
在客户端开发中,导航栏是必不可少的设计元素之一。但纵观很多国内的App,基本都是最为基础的导航栏,缺乏新意。
在本章中,我们就试试使用SwiftUI
构建一个伸缩式导航栏,作为练习。
那么,让我们开始吧。
项目搭建
首先,创建一个新的SwiftUI
项目,命名为SwiftUITabView
。
收缩视图
样式设计方面,由于我们需要构建一个伸缩式的导航栏,那么需要拆解成伸展式和收缩式两种样式效果。
首先我们需要声明一个变量来存储它的状态,示例:
@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() } } }
上述代码中,我们构建了收缩时的样式视图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) }
上述代码中,我们创建了一个展开时的视图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)
这里如果我们要看到最终的效果,我们需要运行模拟器,在真机环境下才能看到最终的交互效果。
项目预览
恭喜你,完成了本章的全部内容!
快来动手试试吧。