Section 05 : Gestures and Events

Section 05 : Gestures and Events - 手势与事件(10’13")

Make your app interactive and animated with the Drag gesture and events in SwiftUI.

在 SwiftUI 中使用拖动手势和事件为应用制作动画与交互。

手势应用是现在的热门,用户已经习惯使用手势操作应用,而且各种需求也越来越多。在 SwiftUI 中,对手势的开发非常容易。iOS 中的手势有很多,如长按、双击、缩放等。本质上和上一节使用状态控制各种修饰和动画一样,但这次不再是简单的布尔值就可以搞定的。

1. 声明状态 (@State)

在 show 之后再声明一个状态 viewState,这是一个 CGSize 类型,包含了宽度和高度,.zero是将其宽高都初始化为 0。

@State var viewState = CGSize.zero  // 声明一个状态,使用 CGSize 类型,并将其 width 和 height 都初始化为 0

2. 添加 gesture 修饰

(1)在卡片 CardView 上,添加 gesture 修饰。其参数类型为 gesture。这里选择拖拽手势DragGesture()。

(2)DragGesture 提供了如 onChanged,onEnded等事件。这里我们选择 onChanged。并且我们以尾随闭包的形式书写事件响应时的程序。

CardView()
    .gesture(
        DragGesture().onChanged { value in		// 尾随闭包
        	self.viewState = value.translation	// 将拖拽事件的返回值传递给 viewState
        }
)

此时在预览窗口并看不出有何变化,这是因为我们还没有使用 viewState 来操作组件。

(3)给卡片添加 offset 修饰。这个修饰要放在手势操作的修饰之前,以免有延迟出现。

CardView()
	.offset(x: self.viewState.width, y: self.viewState.height)	// 将改变的 viewState 应用在组件的偏移量
    .gesture( 
        DragGesture().onChanged { value in		// 尾随闭包
        	self.viewState = value.translation	// 将拖拽事件的返回值传递给 viewState
        }
)

此时可以拖动卡片了,但是松开鼠标左键时,卡片并没有回到初始位置。而且有时候拖拽的时候,卡片的起始移动位置是随机的。所以要进一步完善代码。

(4)在 onChanged 的闭包之后,增加 onEnded 事件响应。类似 onChanged 的事件,我们也写个尾随闭包。

CardView()
	.offset(x: self.viewState.width, y: self.viewState.height)    // 将改变的 viewState 应用在组件的偏移量
	.blendMode(.hardLight)
	.onTapGesture {                         // 定义响应的动作
    	self.show.toggle()                  // 切换 show 的状态
}
	.gesture(
        DragGesture().onChanged { value in      // 拖拽事件的尾随闭包
			self.viewState = value.translation  // 将拖拽事件的返回值传递给 viewState
		}
			.onEnded { value in                     // 拖拽结束,松开鼠标左键,另一个尾随闭包
				self.viewState = .zero              // 复位卡片位置
		}
)

现在好了,卡片可以自动复位了。**注意:**这里并未使用动画。

(5)在卡片 CardView 上添加动画修饰,这也需要在手势操作之前。(还记得修饰器的应用是有顺序的吗?🤪)这次我们选择 spring 动画。

CardView()
	.offset(x: self.viewState.width, y: self.viewState.height)    // 将改变的 viewState 应用在组件的偏移量
	.blendMode(.hardLight)
        .animation(.spring(response: 0.3, dampingFraction: 0.5, blendDuration: 0))	// 使复位的动作更连贯
	.onTapGesture {                         // 定义响应的动作
    	self.show.toggle()                  // 切换 show 的状态
}
	.gesture(
        DragGesture().onChanged { value in      // 拖拽事件的尾随闭包
			self.viewState = value.translation  // 将拖拽事件的返回值传递给 viewState
		}
			.onEnded { value in                     // 拖拽结束,松开鼠标左键,另一个尾随闭包
				self.viewState = .zero              // 复位卡片位置
		}
)
Spring 动画

是 iOS 中常见的动画形式,是一种动画计时,因为有动量,所以可以反弹。由于模拟了物理学的状态,所以距离越远,动量越大,复位的速度就越快。

默认值不是很明显,另一个 spring 的构造函数提供了更多的调整参数。

  • response:数值越小,复位越快,建议值为 0.3-0.6。

  • dampingFraction:数值越小,反弹越大,弹簧效果越明显。建议值 0.6 。

  • blendDuration:视频说猜测为动画过渡的时间

3. 修改其他卡片

为了让另外两张卡片能跟随我们拖动的卡片,可以给它们也添加上 offiset 修饰器。复制下面的代码,粘贴到每个 BackCardView中现有的 offset 修饰的后面。

.offset(x: self.viewState.width, y: self.viewState.height)

预览中可以看见另外两张卡片也跟随一起移动了。

4. 完善动画

(1)在 onChanged 的响应中,增加对状态 show 的更新。键入下面的代码到 onChanged 的代码块中。

self.show = true

通过预览,可以看见拖动时,其他两张卡片为展开的状态。

(2)在 onEnded 的响应中,也加上对状态 show 的更新。键入下面的代码到 onEnded 的代码块中。

self.show = false	

这样可以在释放鼠标左键时,所有的卡片都复位到最初的位置。

总结

本节代码请参见 GitHub码云

  • 状态可以用来控制控件的行为,状态要在 body 之前声明,根据要控制的行为选择状态的变量类型。
  • 手势的开发应用中最常遇到的,用户通过手势进行操作并与应用交互。常见的手势有 DragGesture、TapGesture、LongPressGesture、RotationGesture 等。
  • 手势通过响应事件修改状态。一般可能响应的事件有:onChanged、onEnded 。
  • 将修改的状态应用到组件的修饰器上,组件即可以按照手势的操作改变展示。
  • Spring 动画是一种具有动量的动画,主要参数有 response、dampingFraction 等。
接下来

深入研究动画中的定时曲线、延时速度和重复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值