ios - SwiftUI - 匹配几何效果同步子视图大小
问题描述
我正在实现自定义菜单视图,从顶部尾随位置过渡外观。我正在使用matchedGeometryEffect
视图背景。问题在于第二视图的子视图。它们出现在动画结束之前。你可以在下面看到:
如何将这些按钮视图与父视图的动画同步?
在我的代码下面:
struct ContentView: View {
@State var show = false
@Namespace var namespace
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 0) {
Spacer()
Button(action: {
withAnimation(.linear(duration: 1.2)) { // Longer duration for demo of issue
show.toggle()
}
}) {
Image(systemName: "ellipsis.circle")
.font(.title3)
.background( !show ?
Color.clear
.matchedGeometryEffect(id: "topMenuToggle", in: namespace, properties: .position)
: nil
)
}
}
.padding()
Color.clear
.overlay(
show ? MenuView(namespace: namespace) : nil
, alignment: .topTrailing
)
}
.foregroundColor(.white)
.background(Color.black.ignoresSafeArea())
}
}
struct MenuView: View {
let namespace: Namespace.ID
var body: some View {
VStack(spacing: 0) {
Button(action: {
}) {
HStack(spacing: 0) {
Text("Save video")
.font(.body)
Spacer(minLength: 0)
Image(systemName: "arrow.down.circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 20)
}
}
.padding(.top, 18)
.padding(.bottom, 18)
.padding(.horizontal, 14)
Rectangle()
.fill(Color.white.opacity(0.1))
.frame(maxWidth: .infinity, maxHeight: 1)
Button(action: {
}) {
HStack(spacing: 0) {
Text("Report")
.font(.body)
Spacer(minLength: 0)
Image(systemName: "exclamationmark.bubble")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 20)
}
}
.padding(.top, 16)
.padding(.bottom, 18)
.padding(.horizontal, 14)
}
.foregroundColor(.white)
.frame(width: 250)
.background(
Color.white.opacity(0.2)
.matchedGeometryEffect(id: "topMenuToggle", in: namespace, anchor: .bottomLeading)
)
.cornerRadius(12)
}
}
解决方案
我能够通过MatchedGeometryEffect
为每个行项目和源视图添加来修复动画。也许这不是正确的方法,但它以某种方式起作用。修改后的代码:
Button(action: {
withAnimation(.easeInOut(duration: 1.2)) {
show.toggle()
}
}) {
Image(systemName: "ellipsis.circle")
.background( !show ?
Color.clear
.matchedGeometryEffect(id: "topMenuBg", in: namespace, properties: .position)
.matchedGeometryEffect(id: "topMenuRow0", in: namespace, properties: .position)
.matchedGeometryEffect(id: "topMenuRow1", in: namespace, properties: .position)
.matchedGeometryEffect(id: "topMenuRow2", in: namespace, properties: .position)
: nil
)
}
MenuView.swift
VStack(spacing: 0) {
Button(action: {}) {
HStack(spacing: 0) {}
}
.matchedGeometryEffect(id: "topMenuRow0", in: namespace)
Rectangle()
.fill(Color.white.opacity(0.1))//
.frame(maxWidth: .infinity, maxHeight: 1)
// Before frame() the height is broken weirdly
.matchedGeometryEffect(id: "topMenuRow1", in: namespace)
Button(action: {}) {
HStack(spacing: 0) {}
}
.matchedGeometryEffect(id: "topMenuRow2", in: namespace)
}
.frame(width: 250)
.background(
Color.white.opacity(0.2)
.matchedGeometryEffect(id: "topMenuBg", in: namespace, anchor: .bottomLeading)
)
演示:
推荐阅读
- postgresql - 如何在 PostgreSQL 中使用相似的列连接两个表并将不匹配的字段保留为 NULL 或保持不变
- powershell - 无法加载文件或程序集 - Powershell
- r - 将 `emmeans::joint_tests()` 输出中的 p 值格式保留在针织 pdf 中
- r - macOS 上 R 中的 BLAS 设置
- scala - 使用 circe 过滤结果 JSON
- java - 实例化作业 Quartz 时出现异常
- c - vlsi 放置中的单元格重叠去除
- postgresql - 加快 Postgres 中的 autovacuum
- javascript - 以 d3 惯用方式插入基于子属性的 d3 元素
- prolog - 如何使用从 DCG Prolog 1 转换的普通子句?