在SwiftUI中,如果我们想要给app添加一个到导航栏,可以使用NavigationStack控件,需要注意的是NavigationStack是iOS 16之后增加的,旨在替代原来的NavigationView,所以如果你的app 运行在iOS 16之前的版本需要使用NavigationView

在之前的文章中,我们已经接受了NavigationStack的基本使用,接下来我们将主要介绍NavigationStack自定义,即自定义导航栏样式。

初始项目代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct ContentView: View {
var books: [String] = ["三国演义","水浒传", "红楼梦", "西游记"]
var body: some View {
NavigationStack {
List(books, id: \.self) { book in
NavigationLink {
DetailContentView(book: book)
} label: {
Text(book)
.bold()
}
}
.navigationTitle("四大名著")
}
}
}

struct DetailContentView: View {
var book: String
var body: some View {
Text(book)
}
}
阅读全文 »

在 SwiftUI 中,List 是非常常用的一个组件。它可以帮助我们快速实现一个列表视图。

假设,我们现在下面这样的一个List示例:

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
struct ContentView: View {
var books: [String] = ["三国演义","水浒传", "红楼梦", "西游记"]
var body: some View {
VStack {
List(books, id: \.self) { book in
Text(book)
}
.listStyle(.inset)
}
}
}

针对List,我们可以进行很多的样式设置。

阅读全文 »

在之前关于隐式动画显式动画的文章中,我们都是将动画添加给一个已经存在的视图。在 SwiftUI,它允许我们去定义一个视图的出现和移除,这被叫做过渡(Transitions)

默认情况下,SwiftUI 中的视图的出现和移除使用的fade-infade-out过渡效果。除此之外,SwiftUI 也内置了slidemoveopacity等过渡效果。

构建一个简单的过渡效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct ContentView: View {
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 10)
.frame(width: 300, height: 300)
.foregroundStyle(.green)
.overlay {
Text("显示详情")
.font(.system(.largeTitle, design: .rounded))
.bold()
.foregroundStyle(.white)
}

RoundedRectangle(cornerRadius: 10)
.frame(width: 300, height: 300)
.foregroundStyle(.purple)
.overlay {
Text("哇哦,详情信息")
.font(.system(.largeTitle, design: .rounded))
.bold()
.foregroundStyle(.white)
}
}
}
}
阅读全文 »

在上一篇文章中,我们已经介绍了 SwiftUI 中的隐式动画显式动画

在 SwiftUI中,只需要更多的关注动画的开始和结束,动画的过程由 SwiftUI 帮我们自动完成。接着我们来实现一些常见的动画效果。

创建一个加载动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct ContentView: View {
@State var isLoading: Bool = false
var body: some View {
ZStack() {
Circle()
.trim(from: 0, to: 0.8)
.stroke(lineWidth: 10)
.fill(.green)
.rotationEffect(.degrees(isLoading ? 360 : 0))
.animation(.default.repeatForever(autoreverses: false), value: isLoading)
}
.frame(width: 100, height: 100)
.onAppear {
isLoading = true
}
}
}
阅读全文 »

SwiftUI 给我们提供了两种动画的实现方式: 隐式(implicit)动画显式(explicit)动画。这两种动画方式都可以让我们给视图添加动画和过渡。隐式动画通过修饰器animation给视图添加动画效果,显式动画则是使用withAnimation代码块的方式添加到视图。

隐式动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct ContentView: View {
@State var circleColor: Bool = false
@State var heartColor: Bool = false
@State var heartSize: Bool = false
var body: some View {
ZStack() {
Circle()
.frame(width: 150, height: 150)
.foregroundStyle(circleColor ? Color(.systemGray5) : .red)
Image(systemName: "heart.fill")
.foregroundStyle(heartColor ? .red : .white)
.font(.system(size: 80))
.scaleEffect(heartSize ? 1.0 : 0.5)
}
.onTapGesture {
// 每次点击之后,三个状态值都进行取反操作
circleColor.toggle()
heartColor.toggle()
heartSize.toggle()
}
}
}

在上面的代码中,我们实现了:

  1. 使用@State定义了三个状态变量,用来控制圆的颜色、❤️的颜色以及大小;
  2. 使用Circle绘制了一个圆,然后在这个圆显示一个系统的图标,将二者使用ZStack进行组合;
  3. ZStack添加 一个点击手势onTapGesture,每次点击都对三个状态值进行取反操作,即toggle
  4. 运用三目运算符 根据不同的状态值显式不同的颜色和大小。
阅读全文 »

了解 Path

在 SwiftUI 中,如果想要绘制线条或者形状,可以使用PathPath 是一个结构体用来实现2D 形状的绘制。

如果我们想要绘制下面的形状,

代码如下:

1
2
3
4
5
6
7
Path() { path in
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 300, y: 20))
path.addLine(to: CGPoint(x: 300, y: 200))
path.addLine(to: CGPoint(x: 20, y: 200))
}
.fill(.green) // 填充色
阅读全文 »

在 SwiftUI 中,状态管理是一个非常重要的概念。假设我们有一个播放音乐的 app,当我们点击播放按钮▶️后,按钮的状态从暂停状态⏸️切换到了播放状态。这里我们可以理解为播放的状态从一个状态转移到了另一个状态,当然,在实际的应用中,我们可能存在很多个状态,当状态发生变化时,app 需要根据状态切换到对应用户界面,即 UI。

SwiftUI内置了状态管理的方式,它使用@State属性包装器去修饰一个变量,这个状态变量会被 SwiftUI 自动存储到应用内,当这个变量的值发生变化时,SwiftUI 会自动重新计算和更新视图,即更新 UI。

@State的基本使用

首先,我们来看一下下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct ContentView: View {
@State var playStatus: Bool = false // 当为 true 表示正在播放
var body: some View {
VStack {
Button(action: {
playStatus.toggle() // 布尔值取反
}, label: {
Image(systemName: playStatus ? "stop.circle.fill" : "play.circle.fill" )
.resizable()
.frame(width: 80, height: 80)
.foregroundStyle(playStatus ? .red : .green)
})
}
}
}
阅读全文 »

使用渐变色作为按钮的背景颜色

在 SwiftUI 中,我们不仅仅能使用一个明确的颜色作为按钮的背景色,也可以使用渐变色作为按钮的背景色。

1
2
3
4
5
6
7
8
Button(action: {
}, label: {
Text("Button")
})
.padding()
.foregroundStyle(.white)
.background(.linearGradient(Gradient(colors: [.red, .blue]), startPoint: .leading, endPoint: .trailing))
.clipShape(RoundedRectangle(cornerRadius: 10, style: .circular))

在上面的示例中,我们使用了linearGradient创建了一个线性渐变色作为按钮的背景颜色,linearGradient需要三个参数,

  • 参数一是一个Gradient类型的对象,需要给它设置一个Color类型数组作为渐变的颜色;
  • 参数二和参数三分别是渐变的开始点结束点,例如示例中表示的是渐变从左到右进行。

具体的效果如下:

阅读全文 »

在 SwiftUI 中,Button 是一个视图,它可以响应触摸点击事件。Button 视图有一个基本的结构,包括标题(label)动作(action)。动作是一个在按钮被点击时触发的函数。

按钮的定义

下面是一个简单的 Button 示例:

1
2
3
Button("按钮") {
print("按钮被点击了")
}

在上面的代码中,我们定义了按钮的文字按钮和点击的响应事件print("按钮被点击了")。除了这种方式,我们还可以使用另外一种常用的方式定义一个按钮:

1
2
3
4
5
Button {
print("按钮被点击了")
} label: {
Text("按钮")
}
阅读全文 »
0%