struct ContentView: View {
var body: some View {
VStack {
Text("Turtle Rock")
.font(.title)
.padding()
Text("Joshua Tree Nation Park")
.font(.title2)
}
}
}
⑤ 设置 VStack 初始化参数为左对齐内部的子视图,默认情况下,栈会把内部视图在自己的主轴上居中对齐,并自动计算各子视图的间距。下一步要添加一个 Text 控制用来描述公园的状态,它水平排列在位置信息的右边;
⑥ 在画布内,command 按下的同时点击位置视图,在d出的菜单中选择嵌入到水平栈中 Embed in HStack;
⑦ 在位置控件的后面加一个公园状态的 Text 视图,并把占位文字改为 California,字体设置为子标题样式;
⑧ 为了水平布局使用整个屏幕宽度,在位置控件和公园状态控件中间添加一个 Spacer 控件,用来填充两个控件中间的空白部分,并把两个控件分别顶向屏幕的两侧;Spacer 是一个可以伸缩的空白控件,它负责占用其它控件布局完成后剩下的所有空间;
⑨ 使用 padding() 修改器给地标信息内容视图整体加内边距;
四、创建自定义图像视图 Image
有了地标名称、地标位置及状态视图,下一步再添加一个地标图片视图,这个图片视图将自定义遮罩 mask、边框 border 和阴影 shadow;可以从控件加中拖一个 Image 到画布,或直接写代码到代码编辑器中。在项目资源文件中找到 turtlerock.png 图片,把它拖入资源编辑器 asset catalog editor 中,Xcode 会创建一个新的图片集来存放这个图片,然后创建一个 SwiftUI 视图:
选择文件->新建->文件,打开模板选择器,在用户界面(User Interface)板块下,选择 SwiftUI View 并点击下一步,命名为 CircleImage.swift,并点击创建(Create),现在已经准备好插入图片并修改布局来满足设计目标:
用 Image 替换 Text,并使用 turtlerock 图片初始化 Image 视图;
添加 clipShape(Circle()) 修改器到 Image,给图片添加圆形剪切效果;Circle 是一个形状,它可以被用作遮罩、也可以是圆圈,还可以是圆形填充视图;创建另一个灰色的圆圈并把它作为一个浮层添加到图片上,相当于给图片加了一个灰色边框;给视图添加半径为 10 的阴影;
把圆形边框的颜色改成白色,就完成了自定义图片视图的创建:
五、UIKit 视图与 SwiftUI 视图混合使用
现在要创建一个地图视图,可以使用 MapKit 中的 MKMapView 视图类来渲染地图,要在 SwiftUI 中使用 UIView 及其子类,需要把这些 UIView 包裹在一个遵循 UIViewRepresentable 协议的 SwiftUI 视图中,SwiftUI 中也包含适配 WatchKit 和 AppKit 的类似的协议:
创建一个自定义视图用来容纳和显示 MKMapView:
选择文件->新建->文件,选择 iOS 平台,选择 SwiftUI View 模板,并点击下一步(Next),命名文件为 MapView.swift,并点击创建(Create);
代码中导入 MapKit 引用,声明 MapView 遵循 UIViewRepresentable 协议,UIViewRepresentable 协议要求实现两个方法 UIView(context:) 和 updateUIView(_:context:),第一个方法用来创建 MKMapView,第二个方法用来配置视图响应状态变化;
替换 body,用 makeUIView(context:) 方法来代替,创建并返回一个空的 MKMapView;
创建方法 updateUIView(_:context:),在方法内部设置地图视图的坐标为 Turle Rock 的中心。在静态模式下预览时,只会渲染 SwiftUI 视图的部分,因为 MKMapView 是 UIView 的子类,所以需要切换到实时预览模式下才能看到地图被完全渲染出来;
点击 Live Preview(实时预览)按钮,可能需要点击 Try Again 和 Resume 按钮来激活预览模式的切换,切换到实时预览模式下不久就可以看到指定地标所在的地图位置:
六、组合地标详情页
我们已经完成了创建一个地标详情页所需要的各种子视图元素:名称、地点、圆形图片以及位置地图,现在可以把这些视图元素组合在一起形成地标详情页的整个视图:
在项目工程浏览器中选择 ContentView.swift 文件;body 属性中嵌入一个 VStack 视图,它内部包含另一个 VStack 视图,内部的 VStack 视图又包含三个 Text 视图;在外层 VStack 的顶部添加自定义的地图视图 MapView,并使用 frame(width:height:) 设置视图大小。当只指定高度时,宽度会自动计算为父视图的宽度,在这里就是屏幕宽度;点击 Live Preview 按钮进入实时预览模式,查看地图渲染情况,在实时预览模式下可以编辑视图,最新的改动也可以实时的刷新出来;在 MapView 后面再添加一个 CircleImage 视图;为了让图片视图叠放在地图视图的上面,可以设置图片视图的垂直偏移量为 -130,图片视图的底部内边距也为 -130,这个效果就是把图片垂直上移了 130,同时和下面的文字区域留出了 130 的空白分隔区;在外层 VStack 内部的最下面加上 Spacer,可以让上面的视图内容顶到屏幕的上边;为了让地图的视图内容显示在状态栏的下方,可以给 MapView 添加 edgesIgnoringSafeArea(.top) 修改器,这可以让它在布局时忽略顶部的安全区域边距;
七、总结
在声明自定义 SwiftUI 视图时,视图布局要声明 body 属性中;View 协议中要求实现 body 属性,每一个 SwiftUI 视图都遵循 View 协议。有如下代码布局,那么运行视图效果是什么样?
struct ContentView: View {
var body: some View {
CircleImage()
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
Text("Joshua Tree Nation Park")
}
}
}
从 body 属性中返回三个视图:
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
Divider()
Text("Joshua Tree Nation Park")
}
修改器每次都是返回一个新的对象,所以多个修改器可以通过链式调用,配置视图时,使用修改器的方式如下:
Text("Turtle Rock")
.font(.title)
.foregroundColor(.purple)
完整示例:SwiftUI 之如何创建和组合视图。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)