SwiftUI - 从锚定到按钮框架的按钮点击动画到屏幕上
Posted
技术标签:
【中文标题】SwiftUI - 从锚定到按钮框架的按钮点击动画到屏幕上【英文标题】:SwiftUI - Animate view onto screen from button tap anchored to button frame 【发布时间】:2019-07-31 23:58:01 【问题描述】:我创建了一个示例项目来使用颜色显示我的视图布局。这是它的样子:
这是生成它的代码:
struct ContentView: View
@State private var isShowingLeftPopup: Bool = false
@State private var isShowingRightPopup: Bool = false
var body: some View
TabView
VStack
Spacer()
ZStack
Color.red
.frame(height: 200)
HStack(spacing: 15)
Color.accentColor
.disabled(self.isShowingRightPopup)
.onTapGesture
self.isShowingLeftPopup.toggle()
Color.accentColor
.disabled(self.isShowingLeftPopup)
.onTapGesture
self.isShowingRightPopup.toggle()
.frame(height: 70)
.padding(.horizontal)
Color.purple
.frame(height: 300)
当点击两个蓝色矩形中的任何一个时,我想在蓝色矩形正下方的屏幕上制作一个动画视图,填充蓝色矩形和底部标签栏之间的垂直空间。动画目前并不那么重要 - 我不知道如何将条件视图锚定到蓝色矩形的底部并调整其大小以适应下面的剩余空间。
我制作了一个模型,展示了点击左侧蓝色矩形时的样子:
我在本例中使用了固定高度,但我正在寻找一种不依赖于固定值的解决方案。有谁知道如何将绿色矩形锚定到蓝色矩形的底部并动态调整其大小以填充一直到标签栏的垂直空间?
【问题讨论】:
【参考方案1】:您可以从 GeometryReader、Preferences 和 AnchorPreferences 中受益。我写了很多关于他们的文章。要详细了解它们的工作原理,请参考它们:
GeometryReader 文章: https://swiftui-lab.com/geometryreader-to-the-rescue/
偏好文章: https://swiftui-lab.com/communicating-with-the-view-tree-part-1/
具体来说,对于您想要完成的任务,您需要知道蓝色视图和紫色视图(表示绿色视图的下限)的大小和位置。一旦你得到这些信息,剩下的就很容易了。下面的代码就是这样做的:
import SwiftUI
struct MyData
let viewName: String
let bounds: Anchor<CGRect>
struct MyPreferenceKey: PreferenceKey
static var defaultValue: [MyData] = []
static func reduce(value: inout [MyData], nextValue: () -> [MyData])
value.append(contentsOf: nextValue())
typealias Value = [MyData]
struct ContentView: View
@State private var isShowingLeftPopup: Bool = false
@State private var isShowingRightPopup: Bool = false
var body: some View
TabView
VStack
Spacer()
ZStack
Color.red
.frame(height: 200)
HStack(spacing: 15)
Color.accentColor
.disabled(self.isShowingRightPopup)
.onTapGesture
self.isShowingLeftPopup.toggle()
.anchorPreference(key: MyPreferenceKey.self, value: .bounds)
return [MyData(viewName: "leftView", bounds: $0)]
Color.accentColor
.disabled(self.isShowingLeftPopup)
.onTapGesture self.isShowingRightPopup.toggle()
.anchorPreference(key: MyPreferenceKey.self, value: .bounds)
return [MyData(viewName: "rightView", bounds: $0)]
.frame(height: 70)
.padding(.horizontal)
Color.purple
.frame(height: 300)
.anchorPreference(key: MyPreferenceKey.self, value: .bounds)
return [MyData(viewName: "purpleView", bounds: $0)]
.overlayPreferenceValue(MyPreferenceKey.self) preferences in
GeometryReader proxy in
Group
if self.isShowingLeftPopup
ZStack(alignment: .topLeading)
self.createRectangle(proxy, preferences)
HStack Spacer() // makes the ZStack to expand horizontally
VStack Spacer() // makes the ZStack to expand vertically
.frame(alignment: .topLeading)
else
EmptyView()
func createRectangle(_ geometry: GeometryProxy, _ preferences: [MyData]) -> some View
let l = preferences.first(where: $0.viewName == "leftView" )
let r = preferences.first(where: $0.viewName == "rightView" )
let p = preferences.first(where: $0.viewName == "purpleView" )
let bounds_l = l != nil ? geometry[l!.bounds] : .zero
let bounds_r = r != nil ? geometry[r!.bounds] : .zero
let bounds_p = p != nil ? geometry[p!.bounds] : .zero
return RoundedRectangle(cornerRadius: 15)
.fill(Color.green)
.frame(width: bounds_r.maxX - bounds_l.minX, height: bounds_p.maxY - bounds_l.maxY)
.fixedSize()
.offset(x: bounds_l.minX, y: bounds_l.maxY)
【讨论】:
正是我想要的——非常感谢!我从您那里学到的关于 SwiftUI 的知识比其他任何来源都多,因此非常感谢您的帮助。干杯!以上是关于SwiftUI - 从锚定到按钮框架的按钮点击动画到屏幕上的主要内容,如果未能解决你的问题,请参考以下文章
按钮锚定到InputAccessoryView仅在其框架中工作
如何将浮动操作按钮锚定到App ToolBar,就像在指南图像中一样?