【问题标题】:SwiftUI Hero Animation (matchedGeometryEffect) ProblemSwiftUI Hero Animation (matchedGeometryEffect) 问题
【发布时间】:2021-02-03 10:09:53
【问题描述】:

我一直在寻找不同的在线教程,试图拼凑出一个“简单”的英雄动画。图像位于 LazyHGrid 中,点击时应展开至第二张图像。我尽量压缩和简化下面的代码。

我已经用一张图片让它在网格之外工作。

import SwiftUI

struct Item: Hashable {
    let id = UUID()
    var text = "TEXT"
}


struct ContentView: View {
    
    var items = [Item(text: "One"), Item(text: "Two"), Item(text: "Three"), Item(text: "Four"), Item(text: "Five"), Item(text: "Six"), Item(text: "Seven"),Item(text: "Eight"),Item(text: "Nine")]
    
    @State private var isShowingDetail = false
    @State private var selectedItemID: UUID? = nil
    
    @Namespace var animation: Namespace.ID
    
    var body: some View {
        ZStack {
            ScrollView(.horizontal) {
                LazyHGrid(rows: [GridItem(.flexible())], spacing: 10, content: {
                    ForEach(items,id: \.id, content: { item in
                        VStack {
                            Image("Image2")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 200)
                                .matchedGeometryEffect(id: item.id, in: animation)
                                .onTapGesture {
                                    withAnimation(.spring()){
                                        self.selectedItemID = item.id
                                        isShowingDetail.toggle()
                                    }
                                }
                            Text(item.text)
                        }
                    })
                })
            }
            
            if isShowingDetail {
                VStack {
                    Image("Image1")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 300)
                        .matchedGeometryEffect(id: selectedItemID, in: animation)
                        .onTapGesture {
                            withAnimation(.spring()){
                                selectedItemID = nil
                               isShowingDetail.toggle()
                            }
                        }
                    Spacer()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


【问题讨论】:

    标签: swiftui


    【解决方案1】:

    看起来您的 selectedItemIDisShowingDetail 正在互相争斗(并且是多余的,因为 selectedItemID 是可选的。我已经注释掉了几行,它似乎正在工作:

    struct ContentView: View {
        
        @State var items = [Item(text: "One"), Item(text: "Two"), Item(text: "Three"), Item(text: "Four"), Item(text: "Five"), Item(text: "Six"), Item(text: "Seven"),Item(text: "Eight"),Item(text: "Nine")]
        
        //@State private var isShowingDetail = false // <----- here
        @State private var selectedItemID: UUID? = nil
        
        @Namespace var animation: Namespace.ID
        
        var body: some View {
            ZStack {
                ScrollView(.horizontal) {
                    LazyHGrid(rows: [GridItem(.flexible())], spacing: 10, content: {
                        ForEach(items,id: \.id, content: { item in
                            VStack {
                                Image("0")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .frame(width: 200)
                                    .matchedGeometryEffect(id: item.id, in: animation)
    
                                    .onTapGesture {
                                        withAnimation(.spring()){
                                            self.selectedItemID = item.id
                                            //isShowingDetail.toggle()  // <----- here
                                        }
                                    }
                                Text(item.text)
                            }
                        })
                    })
                }
                
                if let selectedItemID = selectedItemID {  // <----- here
                    VStack {
                        Image("1")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 300)
                            .matchedGeometryEffect(id: selectedItemID, in: animation)
                            .onTapGesture {
                                withAnimation(.spring()){
                                    self.selectedItemID = nil
                                   //isShowingDetail.toggle()  // <----- here
                                }
                            }
                        Spacer()
                    }
                }
            }
        }
    }
    

    需要注意的是,如果您再次点击原始图像,细节图像正在缩小,似乎可能会进入一个有趣的状态。不确定是代码的错误还是 matchGeometryEffect 本身的错误。

    【讨论】:

      猜你喜欢
      • 2019-05-26
      • 2022-12-09
      • 2020-10-29
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2022-12-27
      相关资源
      最近更新 更多