如何在 SwiftUI 中结合可折叠行使用 List 自定义行内部内容?

Posted

技术标签:

【中文标题】如何在 SwiftUI 中结合可折叠行使用 List 自定义行内部内容?【英文标题】:How to customize row internal content with List in SwiftUI combining collapsable rows? 【发布时间】:2020-09-06 22:05:39 【问题描述】:

这是topic的后续问题。

如何将行内的“Hello World”卡片固定到其单元格的顶部?当第二张卡片通过点击出来时它不应该移动。

当前状态:

但在行单元格内,它应该与其顶部对齐,就像这张图片中所描绘的那样:

struct ContentView: View 
    var body: some View 
        VStack 
            Text("Hello!")
            List 
                Detail(isExpanded: false)
                Detail(isExpanded: false)
                Detail(isExpanded: false)
            
        
    


struct Detail: View 
@State var isExpanded :Bool = false
var body: some View 
    VStack 
        ZStack (alignment: .bottom)
            ZStack (alignment: .center) 
                RoundedRectangle(cornerRadius: 8)
                    .fill(Color(red: 0.0, green: 1.0, blue: 1.0, opacity: 0.5)).frame(height: 115)
                Text("Helloo!")
            .zIndex(3).frame(height: 115).contentShape(Rectangle()).onTapGesture 
                withAnimation (.linear(duration: 0.1))
                    self.isExpanded.toggle()
                
            
            Button(action: 
            ) 
                ZStack 
                    RoundedRectangle(cornerRadius: 50)
                        .fill(Color(red: 1.0, green: 0.0, blue: 1.0, opacity: 0.5)).frame(height: 70)
                        .cornerRadius(8)
                        .shadow(radius: 3)
                    Text("Test")
                
            .padding([.leading, .trailing], 12)
                //.padding(.top, 6)
                .frame(height: 70)
                .buttonStyle(BorderlessButtonStyle())
                .offset(y: self.isExpanded ? 80 : 0)
                .disabled(!self.isExpanded)
        
        if(self.isExpanded) 
            Spacer()
        
        
    .modifier(AnimatingCellHeight(height: self.isExpanded ? 210 : 115)).background(Color(red: 1.0, green: 0.5, blue: 1, opacity: 0.5))
    
 


struct AnimatingCellHeight: AnimatableModifier 
    var height: CGFloat = 0

    var animatableData: CGFloat 
        get  height 
        set  height = newValue 
    

    func body(content: Content) -> some View 
        content.frame(height: height)
    

编辑

最终结果应该是这样的。倒置的 isExpanded Bool 是我的错……应该反过来。

EDIT 2 上面的代码已更新为最新尝试。您将在下面的 gif 中看到。

差不多到了....在下面的 gif 中,我按下展开的蓝色卡片正在上下移动一点(当增加点击频率时您可以清楚地看到)。否则行为是完美的,只是卡应该上下摆动......

【问题讨论】:

好吧,实际上至于最后应该实现什么还不清楚(还有那个 inverted "isExpanded" 标志让我感到困惑)。是否应该将所有内容都移到顶部(那为什么下面有空闲空间)?你好按钮是否应该调整到顶部?新布局在动画上应该如何表现?等等......因为对您的要求的严格理解导致了克里斯在下面提出的建议(我的第一次尝试是相同的,但我不喜欢出现的内容)。 倒旗是我的错。你说得对。但我添加了我想要实现的截图。从概念的角度来看,克里斯非常接近。但是蓝色的卡片在点击时会上下移动一点。它应该保持稳定而不移动。下面的第二个视图应该移到“Hello!”下面。卡片(如图所示)。 【参考方案1】:

你是这个意思吗? (添加 VStack + Spacer)

struct Detail: View 
    @State var isExpanded :Bool = false
    var body: some View 
        VStack 
        ZStack 
            ZStack 
                RoundedRectangle(cornerRadius: 8)
                .fill(Color(red: 0.0, green: 1.0, blue: 1.0, opacity: 1.0)).frame(height: 115)
                Text("Hello!")
            .zIndex(3).frame(height: 115).contentShape(Rectangle()).onTapGesture 
                withAnimation 
                    self.isExpanded.toggle()
                
            
            Button(action: 
            ) 
                ZStack 
                    RoundedRectangle(cornerRadius: 50)
                        .fill(Color(red: 1.0, green: 0.0, blue: 1.0, opacity: 1.0)).frame(height: 70)
                        .cornerRadius(8)
                        .shadow(radius: 3)
                        Text("Test")
                
            .padding([.leading, .trailing], 12)
                .padding(.top, 6)
                .frame(height: 70)
                .buttonStyle(BorderlessButtonStyle())
                .offset(y: self.isExpanded ? 0 : 40)
                .disabled(!self.isExpanded)
        
            Spacer()
        .modifier(AnimatingCellHeight(height: self.isExpanded ? 120 : 200))
    

【讨论】:

非常接近。当你点击“你好!” “你好!” rect 上下移动 2 点。它应该保持完全稳定而不移动。只有紫色视图应该移动。剩余的列表当然可以移动,因为占用了更多空间。除此之外。这就是我想要实现的目标。 我还在帖子中添加了我想要实现的目标的屏幕截图。但是,如果您知道如何保持卡片稳定,我会接受答案。我可以处理剩下的。我只需要它如何工作的概念。 我正忙于类似的事情,有同样的问题。它在跳跃。我想知道这是否是有意为之的;一种(失败的)字符串效果?如果不是故意的,你解决了吗? BTW,我用的不是List,但是效果差不多,只是稍微动了动。是否使用和不使用 List 容器进行了测试:(

以上是关于如何在 SwiftUI 中结合可折叠行使用 List 自定义行内部内容?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不实际删除行的情况下明显折叠 Silverlight 4 ListBox 中的单行?

如何在 SwiftUI 中制作“显示”式的折叠/展开动画?

我如何使每个查询折叠php

JQuery DataTables - 行分组、求和、可折叠、导出

在 SwiftUI (Xcode 12) 中折叠侧边栏

使用可折叠/可扩展行创建 gridview C# asp.net