引言
在上一篇博客中我们已经介绍了事件与状态的绑定,通过对Button、TextField以及Slider控件的使用也了解了应用对用户操作的相应方式和能力。SwiftUI作为Apple提供的声明式UI框架,使得我们能够更加自然地管理用户的交互方式。
在本篇博客中,我们将重点探讨SwiftUI中的手势以及选择控件:gesture、Picker、DataPicker。这些控件不仅可以扩展应用的功能,还能为用户提供更加多样化的选择方式。通过它们,我们可以轻松实现响应式UI,让我们的应用在交互上更灵活。
添加手势
和UIKit一样,在SwiftUI中的任何视图都可以添加手势识别,而这些手势识别器会有一个闭包,当手势事件被激活时将会调用闭包中的代码。
手势同样也有很多类型,本篇博客中我们就选几个来介绍,因为它们非常相似。
TapGesture(点击手势)
首先是TapGesture,该手势是我们最常用的一个手势。当我们创建点击手势时,可以指定触发手势所需要的点击次数,然后添加一个onEnded闭包,该闭包将会在点击手势结束之后运行。例如下面的代码,每点击一次数量就会加1:
struct ContentView: View {
@State private var count = 0
var body: some View {
VStack {
Image(systemName: "plus")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.red)
.background(
Circle()
.fill(.yellow)
.frame(width: 50, height:50)
)
.padding()
.gesture(
TapGesture()
.onEnded { _ in
count += 1
}
)
Text("Count: \(count)")
.padding()
.background(.green)
}
.padding()
}
}
我们也可以直接使用OnTapGesture()效果是一样的:
Image(systemName: "plus")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.red)
.background(
Circle()
.fill(.yellow)
.frame(width: 50, height:50)
)
.padding()
.onTapGesture {
count += 1
}
LongPressGesture(长按手势)
其次就是LongPressGesture长按手势,用来识别用户在视图上按住的时间,当时间长达到我们指定的最小时长时则会触发该手势的闭包,我们来写一个案例,当长按达到2秒后显示出一个背景图片:
@State private var show = false
var body: some View {
ZStack {
if show {
Image("swift")
.resizable()
.scaledToFit()
.frame(width: 300, height: 300)
}
Image(systemName: "plus")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.red)
.background(
Circle()
.fill(.yellow)
.frame(width: 50, height:50)
)
.padding()
.onLongPressGesture {
show.toggle()
}
}
.padding()
}
DragGesture(拖拽手势)
最后一个是拖拽手势,在实际开发中也是十分常用的,用户按下视图并至少拖拽一定距离后触发。下面的代码创建了一个图像,当用户拖拽至少20个点时就会触发拖拽手势:
@State private var offset = CGSize.zero
var body: some View {
Image(systemName: "plus")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.red)
.background(
Circle()
.fill(.yellow)
.frame(width: 50, height:50)
)
.padding()
.offset(offset)
.gesture(
DragGesture(minimumDistance: 20)
.onChanged { value in
offset = value.translation
}
.onEnded { value in
offset = .zero
}
)
}
运行代码会发现,当我们拖拽时图片会跟随我们的手指来回移动。
选择器
选择器是应用中不必可少的控件,通常选择日期,年龄,地区等等很多场景都会使用到,每个平台也都会提供一些系统的选择器,SwiftUI也为我们提供了丰富的选择器类型,下面我们来一一看一下吧。
Picker(普通选择器)
SwiftUI中的Picker视图成功将UIKit中的UIPicker和UITableView结合在一起。同时还适应了其他操作系统上的不同样式。并且我们不需要关心它到底是如何实现的SwiftUI能够很好地自动适应其环境。
与大多数控件一样,我们必须将选择器的值绑定到一个变量,以跟踪选择器的选择结果。例如下面的代码,创建了一个颜色数组和一个存储下标的整数变量,然后我们来创建一个选择器,并将结果显示到文本视图中:
private let colors = ["红","黄","蓝","绿"]
@State private var seletedIndex = 0
var body: some View {
VStack {
Text("\(colors[seletedIndex])")
.padding()
Picker("颜色", selection: $seletedIndex) {
ForEach(0..<colors.count) {
Text(colors[$0])
}
}
}
}
Picker(分段控制器)
在SwiftUI中,并没有提供像UISegmentedControl一样的分段控制器,而是使用Picker来实现,当我们指定Picker的样式为SegmentedPickerStyle时,则显示为分段控制器,代码如下:
@State private var favoriteColor = 0
var colors = ["Red", "Green", "Blue"]
var body: some View {
VStack {
Text("SegmentedControl")
.padding()
Picker("Favorite Color", selection: $favoriteColor) {
ForEach(0..<colors.count) {
Text(self.colors[$0])
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
DataPicker(日期选择器)
SwiftUI中的DatePiker视图类似于UIKit中的UIDatePicker,提供了多种选项来控制其外观和功能。与所有存储值的控件一样,它需要绑定到某个状态变量中。
例如,下面的代码创建了一个绑定到birthDate属性的日期选择器,并在设置日期时显示其值:
@State private var birthDate = Date()
private var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}
private let maxmiumDate = Date()
var body: some View {
VStack {
Text("日期选择器")
.padding()
DatePicker("出生日期",
selection: $birthDate,
in: ...maxmiumDate,
displayedComponents: .date)
.datePickerStyle(WheelDatePickerStyle())
Text("出生日期: \(birthDate, formatter: dateFormatter)")
.padding()
}
}
结语
在SwiftUI中,通过手势和选择器等控件的组合,用户体验得到了进一步增强。我们可以在简单的声明式代码下完成复杂的交互逻辑,无论是通过 gesture 实现个性化的手势响应,还是通过 Picker 和 DatePicker 提供灵活的数据选择方式。SwiftUI的这种设计,帮助开发者高效构建出动态交互的应用。
希望本篇文章能帮助您理解和运用这些控件,不断提升应用的互动性和用户满意度。SwiftUI的持续更新还将带来更多便利与可能性,让我们一起期待更多创新的功能!