【问题标题】:Is there a way to change a tabItem's image when selected in SwiftUI when using ForEach?使用 ForEach 时在 SwiftUI 中选择时是否可以更改 tabItem 的图像?
【发布时间】:2020-12-21 19:16:06
【问题描述】:

考虑 SwiftUI 中最简单的选项卡视图应用:

struct ContentView: View {
    @State private var selection = 0
 
    var body: some View {
        TabView(selection: $selection){
            Text("First View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("first")
                        Text("First")
                    }
                }
                .tag(0)
            Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("second")
                        Text("Second")
                    }
                }
                .tag(1)
        }
    }
}

每当点击选项卡时,选项卡项目都会重新加载,如果需要,您可以通过将选择与标签进行比较来更改所选选项卡的图像。但是,如果您在变量中有动态数量的选项卡并使用 ForEach 来显示它们,那将不起作用:

struct ContentView: View {
    @State private var selection = 0

    private var items: [AnyView] {
        return [
            AnyView(Text("First View")
                .font(.title)
                .tabItem {
                        VStack {
                            Image("first1")
                            Text("First1")
                        }
                }
                .tag(0)),
            AnyView(Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image("second")
                        Text("Second")
                    }
                }
                .tag(1))
        ]
    }
 
    var body: some View {
        TabView(selection: $selection){
            ForEach(0..<self.items.count) { index in
                self.items[index]
            }
        }
    }
}

视图重新加载时不会调用ForEach 的主体。有没有办法在 TabView 中使用 ForEach 的同时完成更改图像?

【问题讨论】:

  • 这就像用显微镜钉钉子……在预期的模型和视图中使用预期的模型和视图,在预期的视图和所有都可以工作的地方。
  • 感谢您的评论@Asperi。不幸的是,这既不可能也没有帮助。无论如何,我想出了如何做到这一点:stackoverflow.com/a/63710886/1027644.
  • @KerrM 作为旁注,不推荐使用AnyView(请参阅Static Types in SwiftUI)。您可能希望使用来自this question 的一些解决方案重构您的代码
  • 谢谢,我了解使用AnyView 的缺点。

标签: foreach swiftui tabview


【解决方案1】:

尝试以下方法:

struct ContentView: View {
    @State private var selection = 0
 
    var body: some View {
        TabView(selection: $selection){
            Text("First View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: selection == 0 ? "xmark" : "plus")
                        Text("First")
                    }
                }
                .tag(0)
            Text("Second View")
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: selection == 1 ? "xmark" : "minus")
                        Text("Second")
                    }
                }
                .tag(1)
        }
    }
}

【讨论】:

  • 感谢您的回答,但您没有使用ForEach
  • @KerrM 我以为你从 Asperi 那里得到了提示。您的解决方案远非最干净的。我建议尽可能不要使用AnyView,尤其是[AnyView]。您想要实现的目标可能会以更简单的方式实现。这里我只是给你一个例子,如何改变tabItem的图像,你可以很容易地适应你的需要。
  • 啊,谢谢。那只是一个过于简单的例子。我的问题具体是如何使用 ForEach 来做到这一点。
【解决方案2】:

答案在文档中!使用带范围的 ForEach 时:

    /// Creates an instance that computes views on demand over a *constant*
    /// range.
    ///
    /// This instance only reads the initial value of `data` and so it does not
    /// need to identify views across updates.
    ///
    /// To compute views on demand over a dynamic range use
    /// `ForEach(_:id:content:)`.

因此,要完成这项工作,请使用ForEach(_:id:content:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多