有哪些可以接单做任务的网站,无锡网站建设制作,用手机自创游戏,怎么样新建一个网站代码下载
应用的首页是一个纵向滚动的地标类别列表#xff0c;每一个类别内部是一个横向滑动列表。随后将构建应用的页面导航#xff0c;这个过程中可以学习到如果组合各种视图#xff0c;并让它们适配不同的设备尺寸和设备方向。
下载起步项目并跟着本篇教程一步步实践每一个类别内部是一个横向滑动列表。随后将构建应用的页面导航这个过程中可以学习到如果组合各种视图并让它们适配不同的设备尺寸和设备方向。
下载起步项目并跟着本篇教程一步步实践或者查看本篇完成状态时的工程代码去学习项目文件。
添加一个首页视图
已经创建了所有在应用中需要的视图现在给应用创建一个首页视图把之前创建的视图整合起来。首页不仅仅包含之前创建的视图它还提供页面间导航的方式同时也可以展示各种地标信息。
创建一个名为CategoryHome.swift的自定义视图文件添加NavigationSplitView这个NavigationSplitView将会容纳应用中其它不同的视图。配合使用NavigationLink及相关的修改器就可以构建出应用的页面间导航结构设置导航栏标题为Featured
struct CategoryHome: View {var body: some View {NavigationSplitView {Text(Hello, World!).navigationTitle(Featured)} detail: {Text(Select a Landmark)}}
}创建地标类别列表
应用为了便于用户浏览各种类别的地标将地标按类别竖向排列形成列表视图对于每一个类别内的具体地标又把它们按照水平方向排列形成横向列表。组合使用垂直栈(vertical statck)和水平栈(horizontal stack)并给列表添加滚动。
首先从landmarkData.json文件读取类别数据。
1、在Landmark中向Landmark结构添加Category枚举和category属性。landmarkData文件已经为每个地标数据包含了一个category值该类别值为三个字符串值之一。通过匹配数据文件中的名称可以让结构体遵守Codable协议来加载数据
struct Landmark: Hashable, Codable, Identifiable {var id: Intvar name: Stringvar park: Stringvar state: Stringvar description: Stringvar isFavorite: Boolvar category: Categoryenum Category: String, CaseIterable, Codable {case lakes Lakescase rivers Riverscase mountains Mountains}private var imageName: Stringvar image: Image {Image(imageName)}private var coordinates: Coordinatesvar locationCoordinate: CLLocationCoordinate2D {CLLocationCoordinate2D(latitude: coordinates.latitude,longitude: coordinates.longitude)}struct Coordinates: Hashable, Codable {var latitude: Doublevar longitude: Double}
}2、在ModelData中添加一个categories计算字典使用Dictionary结构体的初始化方法init(grouping:by:)把地标数据的类别属性category传入作为分组依据可以把地标数据按类别分组
class ModelData {var landmarks: [Landmark] load(landmarkData.json)var hikes: [Hike] load(hikeData.json)var categories: [ String: [Landmark] ] {Dictionary(grouping: landmarks) { $0.category.rawValue }}
}3、在CategoryHome中创建一个modelData属性。现在需要访问categories稍后还需要访问其他landmark数据。使用List显示地标数据的类别。Landmark.Category是枚举类型它的值标识列表中每一种类别可以保证类别不会有重复定义
struct CategoryHome: View {Environment(ModelData.self) var modelData: ModelDatavar body: some View {NavigationSplitView {List {ForEach(modelData.categories.keys.sorted(), id: \.self) { key inText(key)}}.navigationTitle(Featured)} detail: {Text(Select a Landmark)}}
}#Preview {CategoryHome().environment(ModelData())
}创建地标行
Landmarks在水平滚动的一行中显示每个类别。添加一个新的视图类型来表示行然后在新视图中显示该类别的所有地标。
重用在创建和组合视图中创建的Landmark视图的部分以创建熟悉的Landmark预览。 1、创建一个名为CategoryItem的新自定义视图显示一个地标
struct CategoryItem: View {var landmark: Landmarkvar body: some View {VStack(alignment: .leading) {landmark.image.resizable().frame(width: 155, height: 155).cornerRadius(5)Text(landmark.name).font(.caption)}.padding(.leading, 15)}
}#Preview {CategoryItem(landmark: ModelData().landmarks[0])
}2、定义一个新的视图类型CategoryRow用来展示地标类别行的内容。新建行视图需要存放地标具体类别的展示数据。在CategoryRow.swift中将类别的条目放入HStack中并将其与类别名称分组到VStack中。为行内容指定一个高度并把行内容嵌入到ScrollView中以支持横向滑动。预览视图时可以多增加几个地标数据用来查看列表的滑动是否正常
struct CategoryRow: View {var categoryName: Stringvar items: [Landmark]var body: some View {VStack(alignment: .leading) {Text(categoryName).font(.headline).padding(.leading, 15).padding(.top, 5)ScrollView(.horizontal, showsIndicators: false) {HStack(alignment: .top, spacing: 0) {ForEach(items) { landmark inCategoryItem(landmark: landmark)}}}.frame(height: 185)}}
}#Preview {let landmarks ModelData().landmarksreturn CategoryRow(categoryName: landmarks[0].category.rawValue, items: Array(landmarks.prefix(3)))
}完成类别视图
将行和特色地标图像添加到类别主页。
1、更新CategoryHome的body将类别信息传递给行类型的实例
接下来在视图的顶部添加一个特色地标。要做到这一点需要从地标数据中获得更多信息。
2、在Landmark中添加一个新的isFeatured属性与添加的其他地标属性一样这个布尔值已经存在于数据中只需要声明一个新属性
struct Landmark: Hashable, Codable, Identifiable {var id: Intvar name: Stringvar park: Stringvar state: Stringvar description: Stringvar isFavorite: Boolvar isFeatured: Boolvar category: Categoryenum Category: String, CaseIterable, Codable {case lakes Lakescase rivers Riverscase mountains Mountains}private var imageName: Stringvar image: Image {Image(imageName)}private var coordinates: Coordinatesvar locationCoordinate: CLLocationCoordinate2D {CLLocationCoordinate2D(latitude: coordinates.latitude,longitude: coordinates.longitude)}struct Coordinates: Hashable, Codable {var latitude: Doublevar longitude: Double}
}3、在ModelData中添加一个新的计算特色地标数组其中只包含将isFeatured设置为true的地标
class ModelData {var landmarks: [Landmark] load(landmarkData.json)var hikes: [Hike] load(hikeData.json)var categories: [ String: [Landmark] ] {Dictionary(grouping: landmarks) { $0.category.rawValue }}var features: [Landmark] {landmarks.filter { $0.isFeatured }}
}4、在CategoryHome中将第一个特色地标的图像添加到列表的顶部。在后面的教程中会将这个视图修改成一个交互式轮播图。目前这个视图仅仅展示一张缩放和剪裁后的地标图片。把视图的边距设置为0让展示内容可以尽量贴着屏幕边沿
struct CategoryHome: View {Environment(ModelData.self) var modelData: ModelDatavar body: some View {NavigationSplitView {List {modelData.features[0].image.resizable().frame(height: 200).clipped().listRowInsets(EdgeInsets())ForEach(modelData.categories.keys.sorted(), id: \.self) { key inCategoryRow(categoryName: key, items: modelData.categories[key] ?? [])}.listRowInsets(EdgeInsets())}.navigationTitle(Featured)} detail: {Text(Select a Landmark)}}
}在各节之间添加导航
现在所有类别的地标都可以在首页视图中展示出来用户还需要能够进入应用其它页面的方法。使用页面导航和相关API来实现用户从应用首页到地标详情页、收藏列表页及用户个人中心页的跳转。 1、在CategoryRow.swift中把CategoryItem视图包裹在NavigationLink视图中。CategoryItem这时做为跳转按钮的内容destination指定点击NavigationLink按钮时要跳转的目标视图
struct CategoryRow: View {var categoryName: Stringvar items: [Landmark]var body: some View {VStack(alignment: .leading) {Text(categoryName).font(.headline).padding(.leading, 15).padding(.top, 5)ScrollView(.horizontal, showsIndicators: false) {HStack(alignment: .top, spacing: 0) {ForEach(items) { landmark inNavigationLink(destination: LandmarkDetail(landmark: landmark)) {CategoryItem(landmark: landmark)}}}}.frame(height: 185)}}
}2、使用renderingMode(:)和foregroundColor(:)这两个属性修改器来改变地标类别项的导航样式。做为NavigationLink标签的CategoryItem中的文本会使用Environment中的强调颜色图片可能以模板图片的方式渲染这些都可以使用属性修改器来调整达到最佳效果
struct CategoryItem: View {var landmark: Landmarkvar body: some View {VStack(alignment: .leading) {landmark.image.renderingMode(.original).resizable().frame(width: 155, height: 155).cornerRadius(5)Text(landmark.name).foregroundStyle(.primary).font(.caption)}.padding(.leading, 15)}
}3、接下来将修改应用程序的ContentView以显示一个TabView让用户在刚刚创建的类别视图和现有的地标列表之间进行选择
切换到ContentView并添加要显示的选项卡枚举。为选项卡选择添加一个状态变量并给它一个默认值。创建一个TabView来包装LandmarkList和新的CategoryHome。每个视图上的 tag(_ 修饰符匹配选择属性可以取的一个可能值因此当用户在用户界面中进行选择时TabView可以协调显示哪个视图。给每个Tab一个标签。确保实时预览打开并尝试新的导航。
struct ContentView: View {State private var selection: Tab .featuredenum Tab {case featuredcase list}var body: some View {TabView(selection: $selection) {CategoryHome().tabItem { Label(Featured, systemImage: star) }.tag(Tab.featured)LandmarkList().tabItem { Label(List, systemImage: list.bullet) }.tag(Tab.list)}}
}#Preview {ContentView().environment(ModelData())
}