SwiftUI + 可刷新:当拉动刷新时,大型导航标题会跳转

问题描述 投票:0回答:1

我遇到了下拉刷新和导航栏的问题。 问题是刷新完成后导航标题会跳回顶部(用户实际上没有释放拉动来刷新)。

可以避免吗?不记得 UIKit 有过这个问题。

发生的事情是这样的:

这是我处理数据刷新的 ViewModel 代码:

    @Published var alerts: [Alert] = []

    ....

    func refresh() async {
        do {
            let result = try await repository.fetchAlerts(page: 1, perPage: 20)
            alerts = result.items
        } catch {
            showErrorBanner(error)
        }
    }

查看:

struct AlertsView: View {
    @StateObject private var viewModel = AlertsViewModel()
    @StateObject private var navigationManager = NavigationManager<AppRoutes>()

    var body: some View {
        NavigationStack(path: $navigationManager.path) {
            ScrollView {
                LazyVStack(alignment: .leading) {
                    ForEach(viewModel.alerts) { alert in
                        Text(alert.body)
                    }
                }
            }
            .refreshable {
                await viewModel.refresh()
            }
            .navigationTitle("Alerts")
            .navigationBarTitleDisplayMode(.large)
        }
        .environmentObject(navigationManager)
    }
}

我想也许这只是我的前端代码弄乱了它,但即使使用简单的布局(没有任何样式)也会发生这种情况:NavigationStack - ScrollView - LazyVStack - ForEach - Text。

编辑:此问题仅在

navigationBarTitleDisplayMode
设置为
.large
时发生。
.inline
工作正常...

最小。部署目标设置为 iOS16。

swift swiftui refresh pull-to-refresh refreshable
1个回答
0
投票

我在拉动刷新方面遇到了问题(因为我有一个自定义标头),并且能够找到一个效果非常好的自定义拉动刷新。认为这可能是 SwiftUI 可刷新修改器中的一个故障。

import SwiftUI

struct PullToRefresh: View {
    
    var coordinateSpaceName: String
    var onRefresh: ()->Void
    
    @State var needRefresh: Bool = false
    
    var body: some View {
        GeometryReader { geo in
            if (geo.frame(in: .named(coordinateSpaceName)).midY > 50) {
                Spacer()
                    .onAppear {
                        needRefresh = true
                    }
            } else if (geo.frame(in: .named(coordinateSpaceName)).maxY < 10) {
                Spacer()
                    .onAppear {
                        if needRefresh {
                            needRefresh = false
                            onRefresh()
                        }
                    }
            }
            HStack {
                Spacer()
                if needRefresh {
                    ProgressView()
                }
// You can uncomment this if you want to see where this is occurring in your View 
//                else {
//                    Text("⬇️")
//                }
                Spacer()
            }
        }.padding(.top, -50)
    }
}

我通过添加 .coordinateSpace(name: "pullToRefresh") 将其添加到我的代码中,然后在我的 ScrollView 中插入自定义 PullToRefresh

 PullToRefresh(coordinateSpaceName: "pullToRefresh") {
 // These functions are the ones I want my viewModel to execute. For example, I want to shuffle the images that appear on the home page when the page is refreshed. 
                            viewModel.styles.shuffle()
                            viewModel.posts.shuffle()
                            viewModel.brands.shuffle()
                        }
© www.soinside.com 2019 - 2024. All rights reserved.