隐藏部分之间的SwiftUI动画列表项

时间:2020-07-17 22:28:22

标签: swift swiftui swiftui-list ios14

我正在寻找一个显示为简单文本单元格的字符串列表。通常,它们可能会分为“ a,b和c”部分。当他们开始搜索时,我想对它们进行不同的分组并添加更多数据,请参见“ A和B”部分。您可以将其视为在不搜索时使用更细粒度的部分,而在搜索时使用更广泛的类别。但是,当我尝试隐藏部分时,使用下面的代码,这些单元将无法在部分之间设置动画。

我经历了几次尝试,我认为生成所有可能的部分可能是最好的选择,但是当使用“ isHidden”修饰符时,我无法使动画正常工作。尝试使用和不使用此修饰符,以查看我希望实现的行为。我之前在UIKit中使用可扩散数据源完成了此操作,所以我不确定SwiftUI为何会出现问题。

我的下一个尝试是创建一个包含所有部分的中间阶段。 (a,b,c)->搜索->全部显示(a,b,c,A,B)->隐藏(A,B)

代码

import SwiftUI

struct ContentView: View {
    
    @State var isA = true
    @State var data: [String: [String]] = [
        "Init Sec 1" : [
            "D1.1",
            "D1.2",
            "D1.3"
        ],
        "Init Sec 2" : [
            "D2.1",
            "D2.2",
            "D2.3"
        ]
    ]

    var sections: [String] {
        get {
            var sections = [String]()
            for key in data.keys {
                sections.append(key + "A")
                sections.append(key + "B")
            }
            
            return sections
        }
    }
    func getData(_ ps: String) -> [String] {
        
        var section = ps
        
        if isA {
            if section.hasSuffix("A") {
                section.removeLast()
                return data[section]!
            } else {
                return []
            }
        } else {
            if section.hasSuffix("B") {
                section.removeLast()
                return data[section]!
            } else {
                return []
            }
        }
    }
        
    var body: some View {
        NavigationView {
            List {
                ForEach(sections, id: \.self) { section in
                    Section(header: Text(section)) {
                        ForEach(getData(section), id: \.self) { row in
                            Text(row)
                        }
                    }//.isHidden(getData(section).count == 0)
                    
                }
            }
            .animation(.default)
            .navigationTitle("List Demo")
            .navigationBarItems(trailing:
                HStack {
                    Button(action: {
                        self.data["Sec \(nextSec)"] = [
                            "D\(nextSec).1",
                            "D\(nextSec).2",
                            "D\(nextSec).3"]
                        self.nextSec += 1
                    }) {
                        Text("Add")
                    }
                    Button(action: {
                        /*var sec = sections.randomElement()!
                        var moveSec = self.data[sec]!
                        var moveIdx = Int.random(in: 0..<moveSec.count)
                        var move = self.data[sec]!.remove(at: moveIdx)
                        
                        
                        self.data[sections.randomElement()!]!.append(move)*/
                        self.isA.toggle()
                        
                    }) {
                        Text("Move")
                    }
                }
            )
        }
    }
}


extension View {
    
    /// Hide or show the view based on a boolean value.
    ///
    /// Example for visibility:
    /// ```
    /// Text("Label")
    ///     .isHidden(true)
    /// ```
    ///
    /// Example for complete removal:
    /// ```
    /// Text("Label")
    ///     .isHidden(true, remove: true)
    /// ```
    ///
    /// - Parameters:
    ///   - hidden: Set to `false` to show the view. Set to `true` to hide the view.
    ///   - remove: Boolean value indicating whether or not to remove the view.
    func isHidden(_ hidden: Bool, remove: Bool = false) -> some View {
        modifier(HiddenModifier(isHidden: hidden, remove: remove))
    }
}


/// Creates a view modifier to show and hide a view.
///
/// Variables can be used in place so that the content can be changed dynamically.
fileprivate struct HiddenModifier: ViewModifier {

    private let isHidden: Bool
    private let remove: Bool

    init(isHidden: Bool, remove: Bool = false) {
        self.isHidden = isHidden
        self.remove = remove
    }

    func body(content: Content) -> some View {
        Group {
            if isHidden {
                if remove {
                    EmptyView()
                } else {
                    content.hidden().frame(width: 0, height: 0).background(Color.red)
                }
            } else {
                content
            }
        }
    }
}

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

0 个答案:

没有答案