简介
SwiftUI是Apple推出的现代界面结构,旨在简化界面开发和布局,并提供强大的响应式编程和动画支撑。与UIKit的一个最明显的差异便是:SwiftUI是一个纯coding式的结构,摒弃了UIkit的结合图形界面设计东西构建视图的功用
概念
下面会从SwiftUI的几个根底并且重要的知识概念出发,从而能够大致理清并了解SwiftUI 结构的大致组成结构,到达在运用SwiftUI这个结构时能够愈加理性的目的
- UI 控件
- 常用控件
- 控件款式
- 链式调用
- view modifier
- 动画
- 生命周期
- 视图
- 运用程序
- 适配
UI 控件
在SwiftUI中,有许多常用的UI 控件可用于构建运用程序的用户界面,一起还能对这些UI 控件的款式进行调整,设计出想要的页面作用
常用控件
- Text:用于显现文本内容,支撑自定义款式、字体和颜色
- Label:用于显现带有图标的文本标签,一般用于表示标签或标题
- Button:创立一个可点击的按钮,用于执行操作或导航到其他视图
-
LinkButton:类似于
Button,但用于打开外部链接或导航到其他运用程序 - TextField:用于接受用户的文本输入
- Image:用于显现图画,支撑本地图画和网络图画
- NavigationView:用于创立导航界面的容器
- NavigationLink:创立一个可点击的导航链接
- ScrollView:用于翻滚内容,以显现更多的信息
- List:用于显现可翻滚的列表,支撑分组和行操作
-
Form:类似于
List,但用于创立表单布局,自动习惯键盘弹出 - Alert:用于显现警报音讯和操作
- ActionSheet:用于显现一个带有多个操作选项的弹出菜单
- VStack:垂直仓库布局,用于按垂直方向摆放视图
- HStack:水平仓库布局,用于按水平方向摆放视图
提示
-
Section也是一个 UI 控件,可是不能独自运用,而是用于构建列表和表格的布局组件。Section一般用于将列表或表格中的内容分组显现 -
VStack和HStack是用于页面布局的,常常频频运用
控件款式
在SwiftUI中构建用户界面时,能够运用链式调用和封装 View Modifier来进行款式调整。这些方法使得在不同视图上运用类似的款式变得十分快捷,一起还能够增强代码的可读性和可维护性
1. 链式调用
在SwiftUI中,能够通过链式调用在视图上运用多个修饰符,从而逐步构建视图的款式。每个修饰符调用都会返回一个新的视图,能够在其上持续运用其他修饰符
struct ProfileHeaderView: View {
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
var body: some View {
Image(avatarUrl)
.resizable()
.clipShape(Circle())
.overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
.shadow(radius: radius)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
.frame(width: 60, height: 60)
}
}
上面这个比如是绘制一个包括外框且有动画的头像框,能够看到首要是运用Image这个控件来完结,外框、动画则都是对这个UI 控件的款式进行调整,选用链式调用内置的修饰符来完结
2. 封装 View Modifier
除了运用内置的修饰符外,您还能够创立自定义的View Modifier,将常用的款式封装起来,以便在多个视图中重复运用,这使得你能够在代码中引进更高层次的笼统,使得代码更具可重用性和可维护性
struct ProfileHeaderView: View {
var body: some View {
Image(avatarUrl)
.resizable()
.circle()
.frame(width: 60, height: 60)
}
}
struct CircleModifier: ViewModifier {
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
func body(content: Content) -> some View {
content
.clipShape(Circle())
.overlay(Circle().stroke(Color.orange, lineWidth: lineWidth))
.shadow(radius: radius)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
}
}
extension Image {
func circle() -> some View {
modifier(CircleModifier())
}
}
上面这个比如则是在链式调用的根底上进行了封装,把多个款式封装成一个款式行为,归于更高层次的款式运用。虽然完成的作用是相同的,可是当多处需要运用到上面的款式时,运用View Modifier封装的款式能让你少写更多相同款式代码
动画
在SwiftUI中,能够运用内置的动画功用为UI 控件添加动画作用,以增强用户体验。动画能够运用于特点的更改,从而使控件的状况转换愈加平滑和引人注目
在上面的比如中有运用到动画修饰符,能够看到需要给动画定义一个触发时机
运用动画有两种方法
- 动画修饰符
.animation - 动画API
withAnimation
下面就运用之前的比如对比演示一下两者运用上的一些差异:
@State var lineWidth = CGFloat(4)
@State var radius = CGFloat(7)
// .animation
Image(avatarUrl)
.animation(.default.repeatForever(), value: lineWidth)
.animation(.default.repeatForever(), value: radius)
.onAppear {
lineWidth = 2
radius = 4
}
// withAnimation
Image(avatarUrl)
.onAppear {
withAnimation(.default.repeatForever()) {
lineWidth = 2
radius = 4
}
}
生命周期
SwiftUI的生命周期与UIkit不同挺大的,首先便是没有UIkit那么详细的生命周期函数,然后便是SwiftUI的生命周期分为视图和运用程序两种
- 视图:生命周期函数被缩减为只剩
onAppear和onDisappear两个 - 运用程序:生命周期与
ScenePhase密切相关- .active:运用程序处于活动状况,即在前台运转,用户能够与运用程序进行交互
- .inactive:运用程序处于非活动状况,即在前台运转,但用户不能与运用程序交互
- .background:运用程序处于后台运转状况
SwiftUI中运用程序生命周期的运用案例:
struct MySwiftUIApp: App {
@Environment(\.scenePhase) private var scenePhase: ScenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { newScenePhase in
layoutWithScenePhase(newScenePhase: newScenePhase)
}
private func layoutWithScenePhase(newScenePhase: ScenePhase) {
switch newScenePhase{
case .active:
// code
case .inactive:
// code
case .background:
// code
@unknown default: break
}
}
}
}
适配
在SwiftUI中,适配涉及保证运用程序在不同设备之间(如iPhone和iPad)以及不同屏幕尺度和分辨率之间都能正常显现
下面列举两个SwiftUI针对不同设备类型的适配方案:
- Size Classes(尺度类别)
- UIDevice.current.userInterfaceIdiom
Size Classes
SwiftUI运用尺度类别来表示设备的巨细和方向,如:compact和regular。在视图中运用.horizontalSizeClass和.verticalSizeClass来检测设备的尺度类别,并根据需要运用不同的布局和款式
struct ContentView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@Environment(\.verticalSizeClass) var verticalSizeClass
var body: some View {
VStack(alignment: .leading) {
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
layoutWithUserInterfaceIdiom()
} else {
HStack {
layoutWithUserInterfaceIdiom()
}
}
}
}
}
UIDevice.current.userInterfaceIdiom
UIDevice.current.userInterfaceIdiom 是UIKit中用于判断设备类型的特点,能够在iPhone和iPad之间进行适配,但如果需要在SwiftUI中运用UIKit特点来判断设备类型,也是能够的
struct ProfileHeaderView: View {
@State var userInterfaceIdiom = UIDevice.current.userInterfaceIdiom
var body: some View {
VStack(alignment: .leading) {
if userInterfaceIdiom == .phone {
HStack {
layoutWithUserInterfaceIdiom()
}
} else {
layoutWithUserInterfaceIdiom()
}
}
}
}
小结
关于SwiftUI的学习,与UIkit的学习路线大致上是类似的,但由于SwiftUI是一种全新的声明式结构,运用方法和一些概念可能会有所不同
关于SwiftUI 结构的运用,本文首要叙述了其通用 UI控件、款式、动画、生命周期以及适配问题等,在后续的文章中会陆续对SwiftUI中的特点包装器、缓存以及网络请求进行谈论及总结
