UIScrollView.setContentOffset() cannot set to the specified position in certain cases

25 Views Asked by At

I want to make the effect of the scrollview moving along when the view pops up like this: enter image description here

However, when I scroll the scrollview to the bottom, the following effect occurs: enter image description here

I don't know why the value passed into setContentOffset is different from the contentOffset.

ScrollViewWrapper<Content: View>: UIViewRepresentable:

    public func makeUIView(context: UIViewRepresentableContext<ScrollViewWrapper>) -> UIScrollView {
        let view = UIScrollView()
        view.delegate = context.coordinator
        view.clipsToBounds = false
        view.contentInsetAdjustmentBehavior = .never
        
        // Instantiate the UIHostingController with the SwiftUI view
        let controller = UIHostingController(rootView: content())
        controller.view.translatesAutoresizingMaskIntoConstraints = false  // Disable autoresizing
        view.addSubview(controller.view)
        
        // Set constraints for the controller's view
        NSLayoutConstraint.activate([
            controller.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            controller.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            controller.view.topAnchor.constraint(equalTo: view.topAnchor),
            controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            controller.view.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
        
        return view
    }
    
    public func updateUIView(_ uiView: UIScrollView, context: UIViewRepresentableContext<ScrollViewWrapper>) {

        let newoffset = CGPoint(x: 0, y: self.contentOffset.y + uiView.contentOffset.y)
        if newoffset.y > self.contentOffset.y{
            uiView.setContentOffset(newoffset, animated: true)
        }
    }

ContentView

        VStack(spacing:0){
            Color.blue
                .opacity(0.8)
                .frame(height: 100)
                .zIndex(1)

            ScrollViewWrapper(contentOffset: $contentOffset, scrollViewHeight: $scrollViewHeight, visibleHeight: $scrollViewVisibleHeight) {
                VStack {
                    ForEach(1..<51, id: \.self) { index in
                        Text("Item \(index)")
                            .padding()
                            .frame(maxWidth: .infinity, alignment: .leading)
                    }
                }
                .background(.green)
            }

            
            Button("test"){
                withAnimation(.bouncy){
                    pop.toggle()
                    contentOffset = CGPoint(x: 0, y: pop ? 250 : -250)
                }
                
            }
            .frame(maxWidth: .infinity, maxHeight: pop ? 300 : 50)
            .padding(10)
            .background(.black)
            .opacity(0.8)
        }
        .ignoresSafeArea(.all)
        .background(.red)

    }

Edit:

I found that there is no any issue when setContentOffset(_, animated: false), and withAnimation() set to nil.

Is there any solution with animation?

0

There are 0 best solutions below