SwiftUI 虽然出现了好几年(1.0好像2019年出的,还有SPM也是同一年),现在已经到从1.0到5.0,但受限于对系统的要求(最低iOS13.0,有的要求17.0及以上),每个版本里面差异也很大,语法和Flutter 的Dart 比较像。空闲之余可以先学习下,给有需要的同学做个参考, 官方也有现成案例,展示效果如图:
地标列表:
import SwiftUI
/// 列表
struct LandmarkList : View {
@Environment(ModelData.self) var modelData
/// 仅展示收藏
@State private var showFavoritesOnly = false
/// 数据过滤
private var filterLandmarks:[Landmark] {
modelData.landmarkData.filter { $0.isFavorite == true || !showFavoritesOnly }
}
/// 转场设置
@State private var selectIndex:Int = 0
@State private var _index:Int? = nil
var body: some View {
NavigationView {
List{
Toggle(isOn: $showFavoritesOnly, label: {
Text("Favorites Only")
})
if selectIndex == 0 {
ForEach(filterLandmarks) { landmark in
NavigationLink {
LandMarkDetail(landmark: landmark)
} label: {
LandmarkRow(landmark: landmark)
}
}
}
else{
ForEach(filterLandmarks.indices,id:\.self) { index in
LandmarkRow(landmark: filterLandmarks[index])
.onTapGesture {
_index = index
debugPrint("onTapGesture:{\(index),\(String(describing: _index))}")
}
}
.sheet(isPresented: .constant(selectIndex > 0 && _index != nil),
onDismiss: {
_index = nil
},
content: {
if _index != nil && filterLandmarks.count > _index! {
LandMarkDetail(landmark: filterLandmarks[_index!])
}
})
}
}
.navigationBarTitle("Landmarks", displayMode: .large)
.navigationBarItems(trailing: SegmentButton(selectIndex:$selectIndex))
.animation(.easeInOut, value: 0.5)
}
}
}
#Preview {
let modelData = ModelData()
return LandmarkList()
.environment(modelData)
}
详情:
import SwiftUI
struct LandMarkDetail : View {
@Environment(ModelData.self) var modelData
var landmark : Landmark
var landmarkIndex:Int? {
get{
modelData.landmarkData.firstIndex { $0.id == landmark.id }
}
}
var body: some View {
@Bindable var modelData = modelData
ScrollView {
MapView(coordinate: landmark.locationCoordinate).frame(height: 300)
CircleImage(image: landmark.image(forSize: 250))
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
HStack{
Text(landmark.name)
.font(.title)
FavoriteButton(isSet: landmarkIndex != nil ? $modelData.landmarkData[landmarkIndex!].isFavorite : .constant(false))
}
HStack {
Text(landmark.park)
Spacer()
Text(landmark.state)
}
.font(.subheadline)
.foregroundStyle(.secondary)
Divider()
Text("About \(landmark.name)")
.font(.title2)
Text(landmark.description ?? "")
}
.padding()
Spacer()
}
.navigationBarTitle(landmark.name, displayMode: .inline)
.navigationBarItems(trailing: FavoriteButton(isSet: landmarkIndex != nil ? $modelData.landmarkData[landmarkIndex!].isFavorite : .constant(false)))
}
}
#Preview {
let modelData = ModelData()
return LandMarkDetail(landmark: modelData.landmarkData[0])
.environment(modelData)
}
每天学习一小步,进步一大步,Demo示例