Airbnb学习总结
轮播图 滚动视图 跳转 切换显示的页面 使用枚举类型管理状态 样式封装复用
1.如何写出一个轮播图
-
使用Tabview来实现功能,给它添加一个tabViewStyle .page,然后就会以页的形式来呈现
var body: some View { //image TabView{ code } .tabViewStyle(.page) }
-
添加图片集
var images = [ "listing-1", "listing-2", "listing-3", "listing-4" ]
-
在tabView中使用ForEach遍历所有图片
ForEach(images,id:\.self) { image in //这里写的是需要构建的结构,信息是从上一行传过来的 Image(image) .resizable() .aspectRatio(contentMode: .fill) }
- 如果使用动态编码,就需要使用一个常量:后面写数据的类型,比如Listing
-
但是下面的预览中,我们需要给view传入实际的可以使用的Listing对象,需要有具体的来源
-
完整代码
import SwiftUI // 组件里边只放最必要,并且可以重用的内容 // 就比如这个carouse组件,实现功能就好,frame和边框圆角用的时候再写 struct ListingImageCarouseView: View { let listing:Listing var body: some View { //image TabView{ ForEach(listing.imageUrls,id:\.self){ image in Image(image) .resizable() .aspectRatio(contentMode: .fill) } } .tabViewStyle(.page) } } #Preview { ListingImageCarouseView(listing: DeveloperPreview.shared.listing[0]) }
2.使用ScrollView实现ExploreView滚动视图
-
在ScrollView中添加一个LazyStack,然后在里面使用ForEach循环创建视图
-
如果使用硬编码,可以直接使用 0 … 10 语法来指定生成的数量
ScrollView{ LazyVStack(spacing:30){ ForEach(0 ... 10,id:\.self) { listing in ListingItemView(listing: listing) .frame(height: 330) .clipShape(RoundedRectangle(cornerRadius: 15)) } } }
- clipShape用来剪切视图形状,比如圆形Circle,圆角矩形RoundedRectangle,形状的常用属性是圆角半径-cornerRadius。
3.ExploreView中有多个ItemView,如何进行点击跳转
-
在NavigationStack中实现跳转
-
给ForEach构建的结构外面加一层NavigationLink,参数value是ForEach中传下的listing
-
返回上一界面
-
使用dismiss环境变量
NavigationStackView、Sheet等产生的次级界面,可使用
@Environment(\.dismiss) var dismiss
自行控制消失。//先设置Didmiss环境变量 @Environment(\.dismiss) var dismiss //给按钮添加dismiss方法,返回上级视图 ZStack(alignment:.topLeading){ ListingImageCarouseView(listing: listing) .frame(height: 270) Button{ dismiss() }label: { Image(systemName: "chevron.left") .foregroundColor(.black) .background{ Circle() .fill(.white) .frame(width: 32,height: 32) } //添加这个padding的目的是把返回按钮放到能看见的地方 .padding(32) } }
-
4.如何切换显示的页面(显示不同页面,不是跳转)
-
创建一个Bool类型的Flag,通过反转这个flag的状态实现页面切换
@State private var showView = false
-
给目标View设置一个环境,环境里有一个方法,dismiss,调用它可以返回到上一页面
@Environment(\.dismiss) var dismiss
-
加一个对于flag的判断,并且给需要跳转到另外一个页面的组件添加点击手势(onTapGesture)
// showView是设置的bool类型的flag if showView{ DestinationView() // 我们需要跳转回来,所以子页面中有环境 .environmentObject() }else{ SearchAndFilterBar() .onTapGesture{ withAnimation(.snappy){ // 切换showView的状态 showView.toggle() } } //剩余的其他UI代码 }
5.如何实现搜索框,边框如何设置
7.如何实现日期选择(DataPicker)和人数选择(Stepper)
8.如何使用枚举类型管理状态
-
先创建一个枚举类型
enum DestinationSearchOption{ case location case dates case guests }
-
将enum作为一个State的property
//设置状态变量对应的enum,三个状态同一时间只需要打开一个,所以只赋值一个 @State private var selectedOption:DestinationSearchOption = .location
-
给VStack添加一个属性onTapGesture,说明如果有点击动作,执行什么操作
// 一共有三个互相切换状态的VStack,每个VStack包含两种呈现效果 // 状态使用 onTapGesture 配合enum 实现切换,呈现效果则使用if进行判断,有两套不同的代码 VStack(){ if selectedOption == .location{ // 激活状态下呈现的效果代码 }else{ // 普通的代码 } } .onTapGesture{ // 添加动画 withAnimation{ selectedOption = .location } } // 如果有多个VStack,全都添加
9.如何将样式封装成一个组件,实现复用(modifier)
样式的封装复用和组件稍有不同,它有一个ViewModifyer协议,并且作为一个View返回
structure ViewModifier:ViewModifier{
func body(content:Content) -> same View {
content
.padding()
.background(.white)
.shawod(radius:10)
}
}
10.如何实现响应的Clear按钮,当有内容时显示
添加一个状态判断,当满足什么条件时,有这个按钮,这里使用的是判断是否为空,同时给按钮加上期望的功能。
if !viewModel.searchLocation.isEmpty{
Button("Clear"){
// clear button
viewModel.searchLocation = ""
}
.foregroundStyle(.black)
.font(.subheadline)
.fontWeight(.semibold)
.padding()
}
11.TabView的实现与布局
-
最外层是一个TabView组件,里面可以放多个View视图,属性 .tabItem是最下面每个View显示出来的内容,一般是一个Text和一个Image图标,我们可以使用一个Label同时添加这两个组件
Label("Explore",systemName:"magnifyingglass")
12.listDetailView页面的细节实现
-
### 轮播图忽略safeArea
#### 属性:.ignoresSafeArea( )
-
### 如何实现Detail中part4中的横向滑动效果
#### 主要有三点: - #### 使用ScrollView - #### 横向摆放:给ScrollView添加属性 .horizental - #### .ScrollTargetBehavior(.paging) - #### .paging的作用是让ScrollView中的page完整实现,会有弹跳效果,如果不加,可以拖动到任意一个位置
-
### scrollTargetBehavior
13.如何添加地图
Boss Question : 如何实现动态编码
## 目录结构
## ![](/Volumes/countstarss/iOS-lupin/截屏2024-04-09 08.43.15.png)
14.如何使用外部数据设置地图默认坐标
15.实现city和state的搜索功能
tip1: 只要在struct中声明了常量,那么在引用这个View的时候就需要把这个作为参数传入
Written on April 9, 2024