首页 > 解决方案 > 为什么初始化列表的滚动位置?

问题描述

单击按钮时,将出现半透明视图。

但是,此时,存在列表的滚动位置被初始化的问题。

图 1:单击按钮之前

图2:点击按钮后

下面是我的 SwiftUI 代码。

import SwiftUI

struct ContentView: View {
    @State var isButtonClicked: Bool = false

    var body: some View {
        ZStack {
            // Layer 0
            TabView {
                tableView()
                    .tabItem { Text("Tab Label 1") }
                    .tag(1)
                Text("Tab Content 2")
                    .tabItem { Text("Tab Label 2") }
                    .tag(2)
            }
        
            // Layer 1
                VStack {
                Spacer()
                HStack {
                    Spacer()
                    Button(action: {
                        isButtonClicked.toggle()
                    }, label: {
                        Text("Button")
                    })
                }
                .padding(.trailing, 20.0)
            }
            .padding(.bottom, 60.0)
        
            // Layer 2
            TranslucentView(opacity: 0.6)
                .opacity(isButtonClicked ? 1.0 : 0)
                .onTapGesture {
                    isButtonClicked.toggle()
                }
                .animation(.linear(duration: 0.3))
        }
    }
}

struct TranslucentView: View {
    let opacity: Double

    var body: some View {
        ZStack {
            Color.black
                .opacity(opacity)
        }
        .edgesIgnoringSafeArea(.all)
    }
}

struct tableView: View {
    let items = [
        Item(name: "Apple", counts: 1),
        Item(name: "Apple", counts: 3),
        Item(name: "Apple", counts: 5),
        Item(name: "Apple", counts: 2),
        Item(name: "Apple", counts: 9),
        Item(name: "Apple", counts: 4),
        Item(name: "Apple", counts: 7),
        Item(name: "Apple", counts: 2),
        Item(name: "Apple", counts: 1),
        Item(name: "Apple", counts: 3),
        Item(name: "Apple", counts: 8),
        Item(name: "Apple", counts: 1),
    ]

    var body: some View {
        List(items) { item in
            VStack {
                Text(item.name)
                Text(String(item.counts))
            }
        }
    }
}

class Item: Identifiable {
    let id = UUID()
    let name: String
    let counts: Int

    init(name: String, counts: Int) {
        self.name = name
        self.counts = counts
    }
}

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

我该如何解决这个问题?

*透明视图必须覆盖整个屏幕,包括标签栏。

标签: swiftui

解决方案


在状态改变时body重建,所以tableView重新创建,所以重新初始化。为了避免最后我们需要使视图相等,因此渲染引擎不会在外部更改时重新创建它。

这是一个解决方案(使用 Xcode 12.1 / iOS 14.1 测试)

演示

TabView {
    EquatableView(content: tableView())       // << here !!
        .tabItem { Text("Tab Label 1") }
        .tag(1)
    Text("Tab Content 2")
        .tabItem { Text("Tab Label 2") }
        .tag(2)
}

tableView并符合Equatable如下

struct tableView: View, Equatable {
    static func == (lhs: tableView, rhs: tableView) -> Bool {
        true
    }
    
    let items = [
     // ... other code

推荐阅读