SwiftUI上的动画卡

让我们在SwiftUI上制作带有手势支持的动画卡:



我想添加一个详细的预览,但是gif的大小不是Orthodox。 可以在链接视频教程中查看大预览。


将被要求


SwiftUI现在处于beta版本,并随新的Xcode一起安装,后者也处于beta版本。 好消息是,新的Xcode可以放在旧的Xcode旁边,您几乎不会感到任何痛苦。



您可以从“ Applications部分中的链接下载它。


使用SwiftUI时,您可能已经看到了实时预览。 要激活它以及一些上下文菜单,您需要安装beta macOS Catalina 。 它不会没有痛苦。 我没有打赌,所以我将以老式的方式运行模拟器。


新项目


创建带有附加复选标记的Single View Application SwiftUI



转到ContentView.swift文件。 PreviewProvider的继承人负责预览。 由于我们将不使用它,因此将保留最少的必要代码:


 import SwiftUI struct ContentView: View { var body: some View { } } 

我希望已经对SwiftUI有了一个共识,我们不会SwiftUI琐碎的SwiftUI


卡片


卡是一张一张地排列的,因此我们将使用ZStack 。 让我提醒您,还有两个用于分组元素的选项:水平的VStack和垂直的VStack 。 为了清楚起见:



添加第一张卡:


 struct ContentView: View { var body: some View { return ZStack { Rectangle() .fill(Color.black) .frame(height: 230) .cornerRadius(10) .padding(16) } } } 

在这里,我们添加了一个矩形,涂成黑色,高度为230pt ,将边缘四舍五入为10pt ,并将所有边距设置为16pt


卡中的文本在矩形之后添加到ZStack块中:


 Text("Main Card") .color(.white) .font(.title) .bold() 

运行项目以查看中间结果:



但是有三个!



为了方便起见,我们将MainCard代码:


 struct MainCard: View { var title: String var body: some View { ZStack { Rectangle() .fill(Color.black) .frame(height: 230) .cornerRadius(10) .padding(16) Text(title) .color(.white) .font(.largeTitle) .bold() } } } 

title将出现在初始化器中。 此文字将显示在卡片上。 将卡添加到ContentView ,同时我们将在初始化程序中看到一个新参数:


 struct ContentView: View { var body: some View { return MainCard(title: "Main Card") } } 

我们已经知道如何编写代码,因此立即为背景卡定义一个类:


 struct Card: View { var title: String var body: some View { ZStack { Rectangle() .fill(Color(red: 68 / 255, green: 41 / 255, blue: 182 / 255)) .frame(height: 230) .cornerRadius(10) .padding(16) Text(title) .color(.white) .font(.title) .bold() } } } 

为文本设置不同的颜色和样式。 其余代码重复黑色主MainCard 。 将两个背景卡添加到ContentView 。 卡是一张一张地排列的,因此我们将它们放置在ZStackContentView代码:


 struct ContentView: View { var body: some View { return ZStack { Card(title: "Third card") Card(title: "Second Card") MainCard(title: "Main Card") } } } 

背景卡位于黑色下方,至今尚不可见。 从边缘添加向上偏移和填充:


 Card(title: "Third card") .blendMode(.hardLight) .padding(64) .padding(.bottom, 64) Card(title: "Second Card") .blendMode(.hardLight) .padding(32) .padding(.bottom, 32) MainCard(title: "Main Card") 

现在,结果类似于本教程开始时的声明:



让我们继续进行手势,并同时进行动画。


手势


手势的实施方式将迫使我减少业力并留下有害的评论。



在查看代码之前,请注意-作为示例,它在developer.apple.com上列出。 第一印象是欺骗性的,实际上我喜欢它。


ContentView声明枚举:


 enum DragState { case inactive case dragging(translation: CGSize) var translation: CGSize { switch self { case .inactive: return .zero case .dragging(let translation): return translation } } var isActive: Bool { switch self { case .inactive: return false case .dragging: return true } } } 

DragState将使手势工作更加舒适。 将dragState dragState添加到ContentView


 @GestureState var dragState = DragState.inactive 

会有魔术。



无论在何处使用dragState ,新值都将自动应用。 声明一个手势:


 let dragGester = DragGesture() .updating($dragState) { (value, state, transaction) in state = .dragging(translation: value.translation) } 

向主卡添加手势并设置offset


 MainCard(title: "Main Card") .offset( x: dragState.translation.width, y: dragState.translation.height ) .gesture(dragGester) 

偏移量是否等于访问参数时的值? 不,它将永远相等 。 这是魔术。


卡将跟随 用手指 用鼠标但没有动画:



背景卡还应该更改其位置( 至少我们需要这样做 )。 为他们添加与手势状态相关的代码。 rotation3DEffect将旋转卡,直到手势变为活动状态:


 Card(title: "Third card") .rotation3DEffect(Angle(degrees: dragState.isActive ? 0 : 60), axis: (x: 10.0, y: 10.0, z: 10.0)) .blendMode(.hardLight) .padding(dragState.isActive ? 32 : 64) .padding(.bottom, dragState.isActive ? 32 : 64) Card(title: "Second Card") .rotation3DEffect(Angle(degrees: dragState.isActive ? 0 : 30), axis: (x: 10.0, y: 10.0, z: 10.0)) .blendMode(.hardLight) .padding(dragState.isActive ? 16 : 32) .padding(.bottom, dragState.isActive ? 0 : 32) 

您还可以如何使用3D呢? 我还添加了blendMode 。 这些模式类似于Photoshop和Sketch中的工具。


尽管更改未应用动画,但让我们对其进行修复。


动画制作


您会惊讶它是如此简单。 只需添加一行:


 .animation(.spring()) 

为每张卡添加。 现在,所有更改都将以动画方式应用,在我们的示例中,这些是缩进大小,3D旋转和offset 。 如果需要带有曲线的动画,请使用basic模式。


装饰物


添加与偏移量相关的主视图的阴影和旋转:


 .rotationEffect(Angle(degrees: Double(dragState.translation.width / 10))) .shadow(radius: dragState.isActive ? 8 : 0) 

如果您运行该项目,您将在本教程的开头看到参考。 打开预览不可见,将卡拉到一边以查看效果。



对于寻求者


→可在存储库中找到项目代码


将文件复制到项目就足够了,不需要其他设置。 不要担心,很少的代码是SwiftUI


如果您更方便观看视频,请看一下教程。 顺便说一句,在视频中,我使用了实时预览。


Source: https://habr.com/ru/post/zh-CN456936/


All Articles