Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird ScrollView behaviour when its inside of moving View. SwiftUI

I have container view which can be draged around and it has scrollview inside with bunch of buttons. When i drag the container view scrollViews starts to jump up and down weirdly, also buttons' hitboxes start be way off from actual buttons. (You can see my gif) But when I touch scrollview everything gets back to normal. Demo weird scrollview

This code is purely for testing

That's the main view

    struct ContentView: View {
    @State var width : CGFloat = 300
    @State var height : CGFloat = 300
    var body: some View {
        VStack{
            SecondView(width: width, height: height){
                ScrollView{
                    VStack{
                        ForEach(0...10, id : \.self){ i in
                            
                            TestButton(number: i)
                            
                        }
                    }
                }
            }
            Slider(value: $width, in: 100...500)
            Slider(value: $height, in: 100...500)
        }
    }
}

That's the dragable view

    struct SecondView<Content : View> : View {
    var width : CGFloat
    var height : CGFloat
    var content : () -> Content
    @GestureState private var dragState = DragState.inactive
    @State var position : CGSize = CGSize(width: 0, height: 0)
    var body : some View {
        let dragGesture = DragGesture().updating($dragState){ drag, state, transition in
            state = .dragging(translation: drag.translation)
            
        }.onEnded({drag in
            self.position.height+=drag.translation.height
            self.position.width+=drag.translation.width
        })
        return VStack{
            Handle()
            
            content().padding()
            
        }.frame(width: width, height: height).background(Color.yellow).cornerRadius(10)
            .offset(x: self.position.width + dragState.translation.width, y: self.position.height + dragState.translation.height)
            .gesture(dragGesture)
        
    }
    
    enum DragState {
        case inactive
        case dragging(translation : CGSize)
        
        
        var translation : CGSize {
            switch self {
            case .inactive:
                return .zero
            case .dragging(let translation):
                return translation
            }
        }
        
        var isDragging : Bool {
            switch self {
            case .inactive:
                return false
            case .dragging:
                return true
            }
        }
    }
}

I'm not sure if it is a bug or it's me doing something wrong, but looks like bug Thanks in advance for answers and suggestions

like image 825
SweetPiggy Avatar asked Oct 16 '25 05:10

SweetPiggy


1 Answers

The .offset modifier does not change views layout, so moved view really remains on the same place and hit areas remains on same place, it just drawn in different location.

Thus .offset does not fit for your goal, instead refactor to use .position, which really changes view hierarchy (but affects entire layout as well, so your floating pane should be placed in separated ZStack to avoid others).

like image 119
Asperi Avatar answered Oct 17 '25 19:10

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!