xcode 在SwiftUI中,是否有一种方法可以扩展和收缩视图,以便在视图的扩展版本中显示隐藏的文本和按钮?

wrrgggsh  于 2022-12-19  发布在  Swift
关注(0)|答案(2)|浏览(102)

我正在制作一个简单的任务应用程序,使用ForEach将模型中的任务信息填充到任务行中。我需要一种方法来动画显示任务视图,以打开并显示一些描述文本和两个按钮。我想点击从A切换到B,然后点击返回:
Design Image
我尝试了几种方法。我成功地在一个测试项目中验证了矩形动画的概念,但也有一些问题。矩形从中心点收缩和增长,而不是从底部开始。当我在其中放置文本时,文本不会隐藏,看起来真的很糟糕。

struct ContentView: View {
@State var animate = false
var animation: Animation = .spring()

var body: some View {
    
    VStack {
        Rectangle()
            .frame(width: 200, height: animate ? 60 : 300)
            .foregroundColor(.blue)
            .onTapGesture {
                withAnimation(animation) {
                    animate.toggle()
                }
            }
    }
}

在我的主应用程序中,我可以用另一个打开的视图替换我的第一个任务视图(关闭)。这很有效,但看起来很糟糕,而且它并没有真正做到我想要的。它使用淡入淡出动画有效地用另一个视图替换了这个视图。

ForEach(taskArrayHigh) { task in
if animate == false {
    TaskView(taskTitle: task.title, category: task.category?.rawValue ?? "", complete: task.complete?.rawValue ?? "", priorityColor: Color("HighPriority"), task: task, activeDate: activeDate)
        .padding(.top, 10)
        .padding(.horizontal)
        .onTapGesture {
            withAnimation(.easeIn) {
                animate.toggle()
            }
        }
        .transition(.move(edge: .bottom))
} else if animate == true {
    TaskViewOpen(task: "Grocery Shopping", category: "Home", remaining: 204, completed: 4)
        .padding(.top, 10)
        .padding(.horizontal)
        .onTapGesture {
            withAnimation(.easeIn) {
                animate.toggle()
            }
        }
}

有没有一种方法可以使我原来关闭的视图以动画形式打开并显示描述文本和按钮?

35g0bw71

35g0bw711#

.transition行的方向是正确的,但是您希望确保容器保持不变,内容发生变化--现在,您要替换整个视图。
下面是一个简单的例子来说明这个概念:

struct ContentView: View {
    
    @State var isExpanded = false
    
    var body: some View {
        VStack {
            Text("Headline")
            if isExpanded {
                Text("More Info")
                Text("And more")
            }
        }
        .padding()
        .frame(maxWidth: .infinity)
        .transition(.move(edge: .bottom))
        .background(Color.gray.cornerRadius(10.0))
        .onTapGesture {
            withAnimation {
                isExpanded.toggle()
            }
        }
    }
}

由于您是在ForEach中使用它,因此您可能希望将其抽象到它自己的组件中,因为它需要自己的@State来跟踪扩展状态,如我在这里所示。

根据评论更新

使用PreferenceKey获取可展开视图的高度,以便可以设置帧的动画,并且没有任何内容淡入淡出的示例:

struct ContentView: View {
    
    @State var isExpanded = false
    @State var subviewHeight : CGFloat = 0
    
    var body: some View {
        VStack {
            Text("Headline")
            VStack {
                Text("More Info")
                Text("And more")
                Text("And more")
                Text("And more")
                Text("And more")
                Text("And more")
            }
        }
        .background(GeometryReader {
            Color.clear.preference(key: ViewHeightKey.self,
                                   value: $0.frame(in: .local).size.height)
        })
        .onPreferenceChange(ViewHeightKey.self) { subviewHeight = $0 }
        .frame(height: isExpanded ? subviewHeight : 50, alignment: .top)
        .padding()
        .clipped()
        .frame(maxWidth: .infinity)
        .transition(.move(edge: .bottom))
        .background(Color.gray.cornerRadius(10.0))
        .onTapGesture {
            withAnimation(.easeIn(duration: 2.0)) {
                isExpanded.toggle()
            }
        }
    }
}

struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}
qaxu7uf2

qaxu7uf22#

使用Swift 5,你可以使用with Animation并根据状态隐藏视图。

展开查看器

  • 具有显示和隐藏内部视图的按钮
  • 接收内容视图
struct ExpandViewer <Content: View>: View {
    
    @State private var isExpanded = false
    @ViewBuilder let expandableView : Content
    
    var body: some View {
        VStack {
            
            Button(action: {
                withAnimation(.easeIn(duration: 0.5)) {
                    self.isExpanded.toggle()
                }
                
            }){
                Text(self.isExpanded ? "Hide" : "View")
                    .foregroundColor(.white)
                    .frame(maxWidth: .infinity, minHeight: 40, alignment: .center)
                    .background(.blue)
                    .cornerRadius(5.0)
            }
            
            if self.isExpanded {
                 self.expandableView
            }
            
        }
       
    }
}

使用查看器

ExpandViewer {
  Text("Hidden Text")
  Text("Hidden Text")
}

相关问题