JJ_iOS/JJUNGTABLE/Common/CustomView/ScorllView_Example.swift
2024-06-26 12:38:42 +09:00

104 lines
3.5 KiB
Swift

//
// ScorllView_Example.swift
// RememberbyAnything
//
// Created by Sean Kim on 5/14/24.
//
import SwiftUI
struct ScorllView_Example: View {
@StateObject private var scrollViewModel: ScrollViewModel = ScrollViewModel()
@State var isStartScroll: Bool = true
// scroll
private var scrollObservableView: some View {
GeometryReader { proxy in
let offsetY = proxy.frame(in: .global).origin.y
Color.clear
.preference(
key: ScrollOffsetKey.self,
value: offsetY
)
.onAppear {
scrollViewModel.setOriginOffset(offsetY)
}
}
.frame(height: 0)
}
var body: some View {
ScrollViewReader { scroll in
ScrollView(showsIndicators: false) {
scrollObservableView.id(-1)
}
.onPreferenceChange(ScrollOffsetKey.self) {
scrollViewModel.setOffset($0)
self.isStartScroll = scrollViewModel.isStartScroll
}
//
.overlay(alignment: .top) {
if isStartScroll {
GeometryReader { geo in
Button {
withAnimation {
scroll.scrollTo(-1, anchor: .center)
}
} label: {
Icon.up
.font(.nps(size: 30))
.foregroundStyle(.brandDeepBlue)
.frame(width: geo.size.width, height: isStartScroll ? 30 : 0,alignment: .center)
.padding(.init(top: 10, leading: 0, bottom: 20, trailing: 0))
.background(
LinearGradient(
colors: [.whiteSora, .whiteSora.opacity(0)],
startPoint: .top,
endPoint: .bottom)
)
}
}
}
}
}
}
}
// MARK: - modifier
struct HeightPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
// = PreferenceKey
struct ScrollOffsetKey: PreferenceKey {
static var defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value += nextValue()
}
}
final class ScrollViewModel: ObservableObject {
@Published var offset: CGFloat = 0
@Published var isStartScroll: Bool = false
var originOffset: CGFloat = 0
var isCheckedOriginOffset: Bool = false
func setOriginOffset(_ offset: CGFloat) {
guard !isCheckedOriginOffset else { return }
self.originOffset = offset - 30 //
self.offset = offset
isCheckedOriginOffset = true
}
func setOffset(_ offset: CGFloat) {
self.offset = offset
if self.offset < self.originOffset { isStartScroll = true }
else { isStartScroll = false }
}
}