gpt4 book ai didi

ios - 匹配的几何效果向后动画似乎在 View 后面

转载 作者:行者123 更新时间:2023-12-02 18:07:39 27 4
gpt4 key购买 nike

我正在尝试在列表上使用匹配的几何效果,并且至少对于详细 View 的动画来说,它的工作方式与预期的一样。问题是从详细 View 返回列表单元格的动画似乎在列表后面。

enter image description here

我怎样才能让它正常工作,以便详细 View 缩小回列表单元格?这是我手机的代码:

struct Cell: View {

var exercise: Exercise
var index: Int
var namespace: Namespace.ID

var body: some View {
VStack {
Text(exercise.title)
.matchedGeometryEffect(id: exercise.id, in: namespace)
.font(.title)
.foregroundColor(.white)
.frame(maxWidth: .infinity, alignment: .leading)
.frame(height: 100)
}
.padding(.horizontal)
.padding(.top)
.padding(.bottom, 4)
.background(
RoundedRectangle(cornerRadius: 5, style: .continuous)
.matchedGeometryEffect(id: exercise.id + "background", in: namespace)
.background(Color.clear)
.foregroundColor(Color.gray)
)
.clipped()
}
}

这是列表本身:

struct ListView: View {

var testData: [Exercise]
var namespace: Namespace.ID
@Binding var tappedCellIndex: Int?

var body: some View {
ScrollView {
LazyVStack {
ForEach(testData.indices) { index in
Cell(exercise: testData[index], index: index, namespace: namespace)
.onTapGesture {
withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) {
self.tappedCellIndex = index
}
}
}
}
}
}
}

这是内容 View :

struct ContentView: View {
let testData = [Exercise(title: "Hallo"), Exercise(title: "Bankdrücken"), Exercise(title: "Squats"), Exercise(title: "Seitheben"), Exercise(title: "Klimmzüge"), Exercise(title: "Bizepscurls"), Exercise(title: "Dips"), Exercise(title: "Aufroller"), Exercise(title: "Muscle"), Exercise(title: "Dragon Flies"), Exercise(title: "Hallo"), Exercise(title: "Bankdrücken"), Exercise(title: "Squats"), Exercise(title: "Seitheben"), Exercise(title: "Klimmzüge"), Exercise(title: "Bizepscurls"), Exercise(title: "Dips"), Exercise(title: "Aufroller"), Exercise(title: "Muscle"), Exercise(title: "Dragon Flies")]

@State var tappedCellIndex: Int? = nil
@Namespace var namespace

var body: some View {
ZStack {
VStack {
ListView(testData: testData, namespace: namespace, tappedCellIndex: $tappedCellIndex)
.opacity(tappedCellIndex == nil ? 1 : 0)
.transition(.scale(scale: 1))
}

if let tappedCellIndex = tappedCellIndex {
DetailView(exercise: testData[tappedCellIndex], selectedIndex: $tappedCellIndex, namespace: namespace)
.transition(.scale(scale: 1))
}
}
}
}

这是它应该动画返回的详细 View :

struct DetailView: View {

var exercise: Exercise
@Binding var selectedIndex: Int?
var namespace: Namespace.ID

var body: some View {
VStack(alignment: .leading) {
HStack {
Text(exercise.title)
.matchedGeometryEffect(id: exercise.id, in: namespace)
.font(.title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color.white)
.padding(.top, 12)
Spacer()
Button {
withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) {
selectedIndex = nil
}
} label: {
Text("Klicke hier!")
}
}

Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
.background(
RoundedRectangle(cornerRadius: 30, style: .continuous)
.matchedGeometryEffect(id: exercise.id + "background", in: namespace)
.foregroundColor(Color.gray)
)
}
}

最后这是模型:

struct Exercise: Identifiable, Hashable, Equatable {
var id = UUID().uuidString
var title: String

static func == (lhs: Exercise, rhs: Exercise) -> Bool {
return lhs.id == rhs.id
}

func hash(into hasher: inout Hasher) {
hasher.combine(id)
}

}

对不起,代码太多了。我希望我添加了所有需要的内容。

顺便说一句:我还收到错误“在匹配的几何组中插入多个 View ”。我认为那是因为我在显示详细 View 时没有隐藏列表。我在 stackoverflow 上阅读了关于此的不同意见,在我看来,并不是在所有情况下都需要在显示另一个 View 时隐藏一个 View ,我也许可以忽略错误消息。

我也无法隐藏列表,因为重新加载会刷新列表,我会再次从列表顶部开始,因此向后动画也将不起作用。

如果有任何帮助,我将不胜感激

最佳答案

我肯定会建议显示一个空的占位符以防止“多个插入的 View ”。此外,.frame(maxWidth, maxHeight) 必须位于 .matchedGeometry 之前,因此 View 可以在动画中缩小或增大。

enter image description here

修改后的代码,查看注释:

struct Cell: View {

var exercise: Exercise
var index: Int
var namespace: Namespace.ID

var body: some View {
VStack {
Text(exercise.title)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) // moved + maxHeight!
.font(.title)
.foregroundColor(.white)
.matchedGeometryEffect(id: exercise.id, in: namespace)
}
.frame(height: 100) // moved
.padding(.horizontal)
.padding(.top)
.padding(.bottom, 4)
.background(
RoundedRectangle(cornerRadius: 5, style: .continuous)
.matchedGeometryEffect(id: exercise.id + "background", in: namespace)
.background(Color.clear)
.foregroundColor(Color.gray)
)
// .clipped()
}
}


struct ListView: View {

var testData: [Exercise]
var namespace: Namespace.ID
@Binding var tappedCellIndex: Int?

var body: some View {
ScrollView {
LazyVStack {
ForEach(testData.indices) { index in
// check if tapped
if index != tappedCellIndex {
Cell(exercise: testData[index], index: index, namespace: namespace)
.onTapGesture {
withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) {
self.tappedCellIndex = index
}
}
} else { // display empty space
Color.clear
.frame(height: 100)
}
}
}
}
}
}


struct ContentView: View {
let testData = [Exercise(title: "Hallo"), Exercise(title: "Bankdrücken"), Exercise(title: "Squats"), Exercise(title: "Seitheben"), Exercise(title: "Klimmzüge"), Exercise(title: "Bizepscurls"), Exercise(title: "Dips"), Exercise(title: "Aufroller"), Exercise(title: "Muscle"), Exercise(title: "Dragon Flies"), Exercise(title: "Hallo"), Exercise(title: "Bankdrücken"), Exercise(title: "Squats"), Exercise(title: "Seitheben"), Exercise(title: "Klimmzüge"), Exercise(title: "Bizepscurls"), Exercise(title: "Dips"), Exercise(title: "Aufroller"), Exercise(title: "Muscle"), Exercise(title: "Dragon Flies")]

@State var tappedCellIndex: Int? = nil
@Namespace var namespace

var body: some View {
ZStack {
VStack {
ListView(testData: testData, namespace: namespace, tappedCellIndex: $tappedCellIndex)
.opacity(tappedCellIndex == nil ? 1 : 0)
// .transition(.scale(scale: 1))
}

if let tappedCellIndex = tappedCellIndex {
DetailView(exercise: testData[tappedCellIndex], selectedIndex: $tappedCellIndex, namespace: namespace)
// .transition(.scale(scale: 1))
}
}
}
}


struct DetailView: View {

var exercise: Exercise
@Binding var selectedIndex: Int?
var namespace: Namespace.ID

var body: some View {
VStack(alignment: .leading) {
HStack {
Text(exercise.title)
.frame(maxWidth: .infinity, alignment: .leading) // moved
.matchedGeometryEffect(id: exercise.id, in: namespace)
.font(.title)
.foregroundColor(Color.white)
.padding(.top, 12)
Spacer()
Button {
withAnimation(.spring(response: 0.6, dampingFraction: 0.8)) {
selectedIndex = nil
}
} label: {
Text("Klicke hier!")
}
}

Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
.background(
RoundedRectangle(cornerRadius: 30, style: .continuous)
.matchedGeometryEffect(id: exercise.id + "background", in: namespace)
.foregroundColor(Color.gray)
)
}
}


struct Exercise: Identifiable, Hashable, Equatable {
var id = UUID().uuidString
var title: String

static func == (lhs: Exercise, rhs: Exercise) -> Bool {
return lhs.id == rhs.id
}

func hash(into hasher: inout Hasher) {
hasher.combine(id)
}

}

关于ios - 匹配的几何效果向后动画似乎在 View 后面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72922210/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com