第scrollview错过了由于滚动过程而错过了一些项目

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

测试视图:

struct TestWheel: View { @State var t: Int! = 1 var tList = [1,2,3,4,5,6,7,8,9,10,11,12] var body: some View { #if os(iOS) if #available(iOS 17.0, *) { UksWheelPicker(selected: $t, items: tList, config: UksWheelConfig(itemHeight: 32)) { Text("Text - \($0)") .frame(width: 100) } } #endif #if os(macOS) if #available(macOS 14.0, *) { UksWheelPicker(selected: $t, items: tList, config: UksWheelConfig(itemHeight: 32)) { Text("Text - \($0)") .frame(width: 100) } } #endif } } the phwheelpicker:WheelPicker sample import SwiftUI import Essentials @available(macOS 14.0, *) @available(iOS 17.0, *) public struct UksWheelPicker<T, ItemView>: View where T: CustomStringConvertible, T: Hashable, ItemView: View { @Binding var selected: T? var items: [T] let config: UksWheelConfig var itemView: (T) -> ItemView public init(selected: Binding<T?>, items: [T], config: UksWheelConfig, itemView: @escaping (T) -> ItemView) { _selected = selected self.items = items self.config = config self.itemView = itemView } public var body: some View { ScrollViewReader { reader in ScrollView(.vertical) { LazyVStack(spacing: 0) { SpacingElem() .id("_______1__") ForEach(items, id: \.self) { item in itemView(item) .frame(height: config.itemHeight) .id(item) .onTapGesture { withAnimation { selected = item } } } SpacingElem() .id("_______2__") } .scrollTargetLayout() } .scrollTargetBehavior(.viewAligned) .scrollIndicators(.hidden) .scrollPosition(id: $selected, anchor: .center) .frame(height: config.itemHeight * 7) .mask(LinearGradient(gradient: Gradient(colors: [.clear, .clear, .black, .black, .clear, .clear]), startPoint: .top, endPoint: .bottom)) .onAppear { scrollToNeededElem(reader: reader) } } } } ////////////////////// ///HELPER VIEWs ///////////////////// @available(macOS 14.0, *) @available(iOS 17.0, *) extension UksWheelPicker { @ViewBuilder private func SpacingElem() -> some View { Spacer() .frame(width: 100, height: config.itemHeight * 3) } } ////////////////////// ///HELPERS ///////////////////// @available(macOS 14.0, *) @available(iOS 17.0, *) extension UksWheelPicker { func scrollToNeededElem(reader: ScrollViewProxy) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { withAnimation { if let selected { reader.scrollTo(selected, anchor: .center) } } } } } public struct UksWheelConfig { public let itemHeight: CGFloat public let selectionEnabled: Bool public let selectionColor: Color? public let selectionIsOverlay: Bool public init(itemHeight: CGFloat, selectionEnabled: Bool = true, selectionColor: Color? = nil, selectionIsOverlay: Bool = false) { self.itemHeight = itemHeight self.selectionEnabled = selectionEnabled self.selectionColor = selectionColor self.selectionIsOverlay = selectionIsOverlay } }

这里的问题是,您将
ViewAlignedScrollTargetBehavior

用作滚动目标行为,但是不能假定它与视图的中心保持一致。它实际上与视图顶部保持一致。因此,由于您将(大)间距元素用作第一个项目,因此它可以阻止其在列表顶部附近的项目2和3的正常工作。

即使您在锚固中使用
.scrollPosition
,这是无关的,并且不会改变滚动行为的工作方式。
swift swiftui scrollview
1个回答
0
投票

swiftui水平滚动浏览捕获问题在初始负载上ive devevevie
ScrolltargetLayout不会中心视图其目标

作为一个解决方案,可以将其作为对这两个帖子中第一个帖子的答案提供的自定义可以改编成垂直滚动视图(这是我的答案):

.center
要使用,需要对

visibleItems

ScrollTargetBehaviorSpacingElem

滚动目标行为。

更新视图,并应用了更改。我还在背景中添加了一个水平中线,以视觉确认它正常工作:

LazyVStack


    
	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.