How to only disable scroll in ScrollView but not content view?
Only pass .horizontal
as the scroll axis if you want the view to scroll. Otherwise, pass the empty set.
struct TestView: View {
@Binding var shouldScroll: Bool
var body: some View {
ScrollView(axes, showsIndicators: false) {
Text("Your content here")
}
}
private var axes: Axis.Set {
return shouldScroll ? .horizontal : []
}
}
Disable scrolling from bottom to top in swiftUI scroll view
Use LazyVGrid
and DragGesture
when changed, you only allow scroll to bottom.
struct ContentView: View {
@State private var offset: CGFloat = .zero
var columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
var body: some View {
LazyVGrid(columns: columns) {
ForEach((0...79), id: \.self) {
let codepoint = $0 + 0x1f600
let codepointString = String(format: "%02X", codepoint)
Text("\(codepointString)")
let emoji = String(Character(UnicodeScalar(codepoint)!))
Text("\(emoji)")
}
}
.font(.largeTitle)
.offset(y: offset)
.gesture(DragGesture().onChanged {value in
let translation = value.translation.height
if translation < 1 {
offset = translation
}
})
}
}
Update
You need to track the last offset when scrolling and reset it to zero each time you stop scrolling. This fixes the issue you have addressed in your comment.
struct ContentView: View {
@State private var offset: CGFloat = .zero
@State private var lastOffset: CGFloat = .zero
var columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)
var body: some View {
LazyVGrid(columns: columns) {
ForEach((0...79), id: \.self) {
let codepoint = $0 + 0x1f600
let codepointString = String(format: "%02X", codepoint)
Text("\(codepointString)")
let emoji = String(Character(UnicodeScalar(codepoint)!))
Text("\(emoji)")
}
}
.font(.largeTitle)
.offset(y: offset)
.gesture(DragGesture().onChanged {value in
let translation = value.translation.height
if translation <= lastOffset {
offset = translation
lastOffset = translation
}
}.onEnded { value in
lastOffset = .zero
})
}
}
You do not need to use LazyVGrid
if you your Views are not too many.
SwiftUI: Disable ScrollView scrolling to top if top of screen is touched
This is not a SwiftUI
or Xcode
or ScrollView
problem.
This is a built-in feature of iPhone.
When you tap the top-center edge of the screen, displayed contents will be scrolled up.
Try opening apps like Facebook, WhatsApp, then scroll and tap at the same position, you will see the displayed contents scroll up.
Stop vertical scroll in SwiftUI ScrollView
If ScrollView's height is less than the content's height it will scroll vertically too.
Just make it higher or the content narrower.
Prevent padding above Image at top of ScrollView when scrolling beyond limit in Sheet
Ok, here is possible solution for your case. Tested with Xcode 12b5 / iOS 14.
The idea is to have internal container, that scrolls inside, but reading its coordinate in scroll view coordinate space, compensate image position offsetting it relative to container, which continue scrolling, such giving effect that everything else, ie below image, still has bouncing.
struct DemoView: View {
var image: UIImage?
@State private var offset = CGFloat.zero
var body: some View {
ScrollView {
VStack { // internal container
Image(uiImage: image ?? UIImage())
.resizable()
.aspectRatio((image?.size.width ?? 1) / (image?.size.height ?? 1), contentMode: .fill)
.background(Color(.secondarySystemFill))
.offset(y: offset < 0 ? offset : 0) // compansate offset
ForEach(0..<50) { index in
Text("\(index)")
}
}
.background(GeometryReader {
// read current position of container inside scroll view
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll")).origin.y)
})
.onPreferenceChange(ViewOffsetKey.self) {
self.offset = $0 // needed offset to shift back image
}
}
.coordinateSpace(name: "scroll")
}
}
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
Related Topics
Unexpectedly Large Realm File Size
Multiple Bottom Sheets - the Content Doesn't Load Swiftui
Drag and Reorder - Uicollectionview with Sections
Extend Existing Protocols to Implement Another Protocol with Default Implements
Protocol Extension on an Objc Protocol
Getting Optional("") When Trying to Get Value from Keychain
Swiftui: Prevent Image() from Expanding View Rect Outside of Screen Bounds
Use Cocoapods With an App Extension
"Generic Parameter Could Not Be Inferred" in Swiftui Uiviewrepresentable
String(Contentsofurl:) in Swift 3
Nsurl Found Nil While Unwraping an Optional Value
For Loop Cycle Showing Always the Last Array Value Swift 3 After Http Request
Remove All Non-Numeric Characters from a String in Swift
Is There a Writetofile Equivalent for Swift 3's 'Data' Type