Hello, Everyone,
I'm developing ios app and have a question.
one case that screen of my app has multiple tab including each scrollview, when I change tab scroll offset is initialized.
"Search.Tag" is identifiable and id is different each. and FeedListModel is identifiable also. what's the problem, please give me a tip.
This is my screenshot and codes.
TabView(selection: $model.selected) {
ForEach(model.listByTag, id: \.key) { (tag, list) in
SearchMoreTab(
model: model, feedList: list, tag: tag,
stickyHeaderHeight: $stickyHeaderHeight,
defaultStickyHeaderHeight: defaultStickyHeaderHeight)
.tag(tag)
}
struct SearchMoreTab: View {
@ObservedObject var model: SearchMoreModel
@ObservedObject var feedList: FeedListModel
let tag: Search.Tag
@Binding var stickyHeaderHeight: Float
let defaultStickyHeaderHeight: Float
// scrollableHeight = contentHeight - scrollViewHeight
@State var lastScrollOffset: CGFloat = .zero
@State var scrollOffset: CGFloat = .zero
@State var contentHeight: CGFloat = .zero
@State var scrollHeight: CGFloat = .zero
var body: some View {
ScrollView {
VStack(spacing: 0) {
let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
LazyVGrid(columns: columns) {
ForEach(feedList.feeds) { feed in
FeedCell(count: 2, spacing: 2, padding: 16, feed: feed)
.onAppear {
feedList.onAppear(feed)
}
}
}
}
.padding(.horizontal, 10)
.scrollOffsetGetter($scrollOffset, coordinateId: tag.id)
.heightGetter($contentHeight)
}
.coordinateSpace(name: tag.id)
.heightGetter($scrollHeight)
#if DEBUG
.overlay {
VStack {
Text("scrollable: \(Int(contentHeight - scrollHeight))")
Text("offset \(Int(scrollOffset))")
}
.background(.mint)
.allowsHitTesting(false)
}
#endif
.refreshable {
Task { try await feedList.populate() }
}
.onChange(of: scrollOffset) { offset in
let scrollableHeight = contentHeight - scrollHeight
guard Float(scrollableHeight) > stickyHeaderHeight else { return }
if offset < 0 { return }
if offset > scrollableHeight { return }
guard model.selected == tag else { return }
let diff = Float(lastScrollOffset - offset)
self.lastScrollOffset = offset
stickyHeaderHeight = (stickyHeaderHeight + diff).clamped(to: 0...defaultStickyHeaderHeight)
}
.onLoad {
Task {
try await feedList.populate()
}
}
}
}