编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

SwiftUI入门一:创建并组合视图(下)

wxchong 2024-11-21 22:06:16 开源技术 52 ℃ 0 评论

04 创建自定义的图像视图

在名字和位置都设置好了之后,接下来需要添加地标的图片。

相比在这个文件中添加更多的代码,我们会创建一个自定义的视图将蒙版、边框和投影应用到图片中。


我们从添加图片到项目的资源目录开始。

第一步

在项目文件的Resources文件夹中找到turtlerock.png文件,将它拖放到资源目录的编辑器中,Xcode 会为它创建一个新的图片集。


接下来,我们会为自定义图像视图创建一个新的 SwiftUI 视图。

第二步

选择 File -> New -> File,打开模板选择器。在User Interface版块,选择SwiftUI View并点击Next,将文件命令为 CircleImage.swift 并点击Create。

我们已经准备好要插入图片并修改显示以匹配设计的样式了。

第三步

使用带有 Turtle Rock 图片的Image(_:)初始化器替换原本的文本视图。

struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
    }
}

第四步

添加clipShape(Circle())调用对图片应用圆形剪切蒙版。

Circle类型是一个可以用来当蒙版的形状类型,也可以作为视图画一个圆边或圆形。

var body: some View {
        Image("turtlerock")
            .clipShape(Circle())
    }
}

第五步

使用灰色的描边画出另外一个圆,然后作为叠层添加,为图像添加一个边框。

        Image("turtlerock")
            .clipShape(Circle())
            .overlay(
                Circle().stroke(Color.gray, lineWidth: 4))
    }
}

第六步

接下来,添加 10 个单位的阴影。

            .overlay(
                Circle().stroke(Color.gray, lineWidth: 4))
            .shadow(radius: 10)
    }
}

第七步

将边框的颜色换成白色。

我们就完成的图像视图。

.clipShape(Circle())
            .overlay(
                Circle().stroke(Color.white, lineWidth: 4))
            .shadow(radius: 10)
    }

05 将 UIKit 和 SwiftUI 视图一起使用

现在,我们可以创建地图视图了。我们可以使用 MapKit 的MKMapView类来渲染地图。

要在 SwiftUI 中使用 UIView 的子类,需要将视图嵌套进 SwiftUI 视图并遵守UIViewRepresentable协议。SwiftUI 也包含类似的协议用于 WatchKit 和 AppKit 视图。


要开始构建,我们需要创建一个新的自定义视图用于展示 MKMapView。

第一步

选择 File -> New ->File,选择iOS作为平台,选择SwiftUI View模板,然后点击Next,将文件命名为MapView.swift并点击Create`。


第二步

添加导入 MapKit 语句,并为 MapView 类声明UIViewRepresentable协议。

不要担心 Xcode 显示的错误提示,我们会在之后几步中修复它们。

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

UIViewPresentable协议有两个要求需要添加:一个是创建 MKMapView 的makeUIView(context:)方法,另外一个是配置视图和响应变化的updateUIView(context:)方法。

第三步

将 body 属性替换成makeUIView(context:)方法,方法中创建并返回一个空的MKMapView。

struct MapView: UIViewRepresentable {
    func makeUIView(context: Context) -> MKMapView {
        MKMapView(frame: .zero)
    }
}

第四步

创建updateUIView(context:)方法,在方法中将地图视图的位置设置到正确的坐标让地图显示 Turtle Rock 的位置。

         MKMapView(frame: .zero)
    }

    func updateUIView(_ uiView: MKMapView, context: Context) {
        let coordinate = CLLocationCoordinate2D(
            latitude: 34.011286, longitude: -116.166868)
        let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        uiView.setRegion(region, animated: true)
    }
}

当预览器处理静态模式时,只会渲染 SwiftUI 视图的内容。因为 MKMapView 是 UIView 的子类,需要切换到实时预览才能看到地图。

第五步

点击Live Preview按钮切换到实时预览模式。可能还需要点击预览界面中的Try Again或Resume按钮。

一会儿之后,我们可以看到 Turtle Rock 位置所在的地图。


06 排版详情视图

现在我们有了所有需要的视图-名字及位置、圆形图片和位置所在的地图。

使用我们目前用过的工具,将自定义视图组合并创建最终的 landmark 详情视图设计。


第一步

在项目导航器中,选择ContentView.swift文件。

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            HStack {
                Text("Joshua Tree National Park")
                    .font(.subheadline)
                Spacer()
                Text("California")
                    .font(.subheadline)
            }
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

第二步

将装载三个文本视图的 VStack 视图嵌套进另外一个 VStack 视图。

struct ContentView: View {
    var body: some View {
        VStack {
            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)
                HStack(alignment: .top) {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
            }
            .padding()

第三步

在新添加的 VStack 顶层添加自定义的 MapView。通过frame(width:height:)设置 MapView 的大小。

在只指定 height 参数时,视图会自动将宽度调整到内容的大小。在这个例子中,MapView 会填充所有可用的空间。

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            MapView()
                .frame(height: 300)

            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)
                HStack(alignment: .top) {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
            }
            .padding()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

第四步

点击Live Preview按钮在组合的视图中查看渲染的地图。

在显示实时预览时可以继续编辑视图

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            MapView()
                .frame(height: 300)

            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)
                HStack(alignment: .top) {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
            }
            .padding()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

第五步

在 Stack 中添加 CircleImage。

                .frame(height: 300)

            CircleImage()

            VStack(alignment: .leading) {
                Text("Turtle Rock")

第六步

要将图像视图放置在地图视图上方,给图像视图添加一个-130 单位的竖直方向的偏移,并在底部添加-130 单位的 padding。

这些调整将图像视图上移为文本腾出空间。

            CircleImage()
                .offset(y: -130)
                .padding(.bottom, -130)

            VStack(alignment: .leading) {

第七步

在外层 VStack 的底部添加一个spacer将内容推到屏幕的顶部。

            }
            .padding()

            Spacer()
        }
    }

第八步

最后,为了将地图的内容扩展到屏幕的上边缘,在地图视图上添加edgesIgnoringSafeArea(.top)修饰器。

         VStack {
            MapView()
                .edgesIgnoringSafeArea(.top)
                .frame(height: 300)

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表