ScrollView + DragGesture onChanged conflicts

Hi,

I have been trying to create a bottom sheet view which contains a couple of views inside such as scrollview. In this part of source code work fine however, I've figured out something that when finger interacts with scrollview at first, onChanged listener fired, but drag gesture can not catch onEnded. That's why ui could not handle dragging end operations. I think this is a known issue, but neither I could find any acceptable solution, nor I'm convinced explanations. Would you please give me some feedback, maybe I need to change point of my view and redesign source code.

Thanks.

struct UserInfoRegistrationView: View {
    
    @ObservedObject private var viewModel: UserInfoRegistrationViewModel
    
    @State private var offSet: CGFloat = 0
    
    init(viewModel: UserInfoRegistrationViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {
       
        VStack {
            
            Spacer()
            
            VStack(alignment: .center, spacing: 0) {
                
                    Rectangle()
                        .fill(Color.clear)
                        .frame(height: 40, alignment: .center)
                
                ScrollView(.vertical) {
                    
                    Rectangle()
                        .fill(Color.clear)
                        .frame(height: 40, alignment: .center)
                    
                    VStack(alignment: .leading, spacing: 30) {
                        
                        VStack(alignment: .leading, spacing: 15) {
                            
                            Text("Text 1")
                            Text("Text 2")
                            Text("Text 3")
                            Text("Text 4")
                    }
                    .padding(.horizontal, 30)
                    
                }
                .frame(height: UIScreen.main.bounds.height - 300)
                
            }
            .frame(maxWidth: .infinity)
            .background(
                Color.white
                    .ignoresSafeArea()
            )
            .offset(y: offSet)
            .offset(y: viewModel.showSheet ? 0 : (UIScreen.main.bounds.height - 200))
            .gesture(DragGesture()
                        .onEnded(self.onEnded(value:))
                        .onChanged(self.onChanged(value:)))
            
        }
        .background(
        
            Color.black.opacity(viewModel.showSheet ? 0.4 : 0)
                .ignoresSafeArea()
                .onTapGesture(perform: onTapGesture)
            
        )
        
    }
    
    func onTapGesture() {
        withAnimation {
            viewModel.showSheet.toggle()
        }
    }
    
    func onChanged(value: DragGesture.Value) {
        
        if value.translation.height > 0 {
            offSet = value.translation.height
            debugPresentationLayer("offset : \(offSet)")
        }
    }
    
    func onEnded(value: DragGesture.Value) {
        
        withAnimation(Animation.easeIn(duration: 0.4)) {
            
            let height = UIScreen.main.bounds.height / 3
            
            if value.translation.height > height {
                viewModel.showSheet.toggle()
            }
            offSet = 0.0
            
        }
        
    }
    
}
Terms of Service

Privacy Policy

Cookie Policy