【问题标题】:SwiftUI getting ScrollViewReader to scroll when using Swift structures and id'sSwiftUI 在使用 Swift 结构和 id 时让 ScrollViewReader 滚动
【发布时间】:2021-09-06 15:17:27
【问题描述】:

我有几个简单的 Swift UI 屏幕,它们都在运行一个结构。该结构定义了一个小部件的视图、它的名称以及它进入的顺序。我正在尝试制作一个水平列表,其中每个按钮在按下时都会在滚动视图中居中。这就是我想要做的:

我遇到的问题是我无法让 ScrollViewReader 将 scoll 视图移动到正确位置。它认为这与ID有关,但我不确定。我对 SwiftUI 很陌生,这可能是一个非常基本的问题,但感谢任何帮助!

这是我的结构

struct WidgetView: Identifiable, Hashable{
    static func == (lhs: WidgetView, rhs: WidgetView) -> Bool {
        return lhs.id == rhs.id && lhs.friendlyName == rhs.friendlyName && lhs.order == rhs.order && lhs.selected == rhs.selected
    }
    
    let id = UUID()
    var friendlyName: String
    var view: Any
    var order: Int
    var selected: Bool
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

extension WidgetView {
    static var data: [WidgetView] {
        [
            WidgetView(friendlyName: "News", view: MusicView(), order: 1, selected: false),
            WidgetView(friendlyName: "Music", view: MusicView(), order: 2, selected: false),
            WidgetView(friendlyName: "Ambiance", view: AmbianceView(), order: 3, selected: true),
            WidgetView(friendlyName: "Weather", view: WeatherView(), order: 4, selected: false),
            WidgetView(friendlyName: "Routines", view: MusicView(), order: 5, selected: false)
        ]
    }
}

这是我的两个 SwiftUI 视图,第一个只是小文本框,第二个是滚动视图不起作用。

struct WidgetName: View {
    let widget: WidgetView
    
    var body: some View {
        ZStack(alignment: .center) {
            Color.clear
            Button(action: {
                print("Hello")
            }){
                ZStack{
                    Text(widget.friendlyName)
                        .fontWeight(.semibold)
                        .opacity(0)
                        .padding(widget.selected ? 15: 12)
                        .overlay(
                            RoundedRectangle(cornerRadius: 15)
                                    .fill(Color.white)
                                .opacity(widget.selected ? 1: 0.5)
                        )
                    Text(widget.friendlyName)
                        .fontWeight(.semibold)
                        .foregroundColor(.black)
                        .opacity(widget.selected ? 1: 0.5)
                }
            }
        }.padding()
    }
}

struct WidgetName_Previews: PreviewProvider {
    static var previews: some View {
        WidgetName(widget: WidgetView.data[1])
            .previewLayout(.fixed(width: 400, height: 60))
            .background(Color.purple)
        WidgetName(widget: WidgetView.data[2])
            .previewLayout(.fixed(width: 400, height: 60))
            .background(Color.purple)
        WidgetName(widget: WidgetView.data[3])
            .previewLayout(.fixed(width: 400, height: 60))
            .background(Color.purple)
    }
    
}
    struct WidgetNameStrip: View {
        var widgets: [WidgetView]
    
        var body: some View {
            VStack{
                Spacer()
                ScrollView(.horizontal, showsIndicators: false) {
                    
                    ScrollViewReader { value in
                        
                        Button("Jump to #32") {
                            value.scrollTo(3)
                        }
                        .foregroundColor(.white)
                        
                        HStack(spacing: 10) {
                            ForEach(widgets, id: \.self) { widget in
                                WidgetName(widget: widget)
                            }
                        }
                        
                    }
                    
                }
                .frame(height: 80)
            }
        }
        
    }
    
    struct WidgetNameStrip_Previews: PreviewProvider {
        static var previews: some View {
            WidgetNameStrip(widgets: WidgetView.data)
                .background(Color.purple)
                .previewDevice("iPhone 8")
        }
    }



【问题讨论】:

    标签: ios swift swiftui uiscrollview


    【解决方案1】:

    对于您的代码,正如我所见,它需要使用order 作为视图的id,因为scrollTo 使用id/s 来查找视图,即:

    Button("Jump to #32") {
        value.scrollTo(3)
    }
    .foregroundColor(.white)
    
    HStack(spacing: 10) {
        ForEach(widgets, id: \.self) { widget in
            WidgetName(widget: widget)
                .id(widget.order)     // << here !!
        }
    }
    

    【讨论】:

    • 哇,非常感谢!但是为什么结构中的 id 不起作用?将其归类为可识别还不足以让 scrollTo 找到它吗?
    【解决方案2】:

    基于@Asperi 的响应,您还可以在建立 id 后使用 .scrollTo 上的锚参数。

    Anchor 控制一旦滚动到所选项目在滚动视图内的位置。

    Button("Jump to #32") {
      value.scrollTo(id, anchor: .center)
    }
    

    您可以使用 withAnimation 对其进行动画处理

    withAnimation { value.scrollTo(3, anchor: .center) }
    

    【讨论】:

    • 您缺少一个括号,但感谢您的好主意。现在看起来更流畅了!
    • 我的错误,现在已修复。很高兴我能帮上忙!
    猜你喜欢
    • 2021-03-06
    • 2022-10-17
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多