You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ScrollViewReader的scrollTo方法失效:水平菜单滚动不跟随currentIndex变化求助

问题排查与修复

核心问题1:ScrollViewReader的嵌套顺序错误

你的代码把ScrollViewReader放在了ScrollView内部,这会导致滚动代理(proxy)无法正确关联到外部的ScrollView,自然无法触发滚动操作。必须让ScrollViewReader包裹ScrollView,才能让proxy获取到正确的滚动上下文。

核心问题2:scrollTo的目标ID不匹配

你调用proxy.scrollTo(newValue)时传入的是Int类型的index,但ScrollView里的可滚动元素是T类型的菜单项(ForEach遍历的是items数组的元素),两者ID类型不匹配,proxy找不到对应的滚动目标,所以没反应。


修复后的完整代码

struct ScrollableTabMenu<T: CaseIterable & Hashable & Identifiable>: View  {
    var items: [T]
    var title: KeyPath<T, String>
    @Binding var currentIndex: Int
    @Namespace private var animation
    
    var body: some View {
        // 调整ScrollViewReader位置,包裹ScrollView
        ScrollViewReader { proxy in
            ScrollView(.horizontal) {
                HStack {
                    // 用enumerated()遍历,避免强制解包索引
                    ForEach(Array(items.enumerated()), id: \.element.id) { index, screen in
                        Button {
                            currentIndex = index
                        } label: {
                            Text(screen[keyPath: title])
                                .padding()
                                .overlay(alignment: .bottom){
                                    if currentIndex == index  {
                                        RoundedRectangle(cornerRadius: 6)
                                            .frame(height: 1)
                                            .matchedGeometryEffect(id: "AninamtionTAB", in: animation)
                                    }
                                }
                        }
                        .buttonStyle(.plain)
                        // 给每个按钮绑定index作为ID,和scrollTo目标匹配
                        .id(index)
                    }
                }
                .onChange(of: currentIndex, { _, newValue in
                    withAnimation {
                        proxy.scrollTo(newValue, anchor: .leading)
                        print(newValue)
                    }
                })
            }
            .scrollTargetBehavior(.paging)
            .scrollIndicators(.hidden)
            .contentMargins(.horizontal, 16)
        }
    }
}

额外优化说明

  • 用Array(items.enumerated())遍历替代firstIndex(of:)!,避免强制解包带来的崩溃风险
  • 如果需要让选中项滚动到视图中间,可将anchor: .leading改为anchor: .center

内容的提问来源于stack exchange,提问作者kAiN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:32:56