79317605

Date: 2024-12-30 12:39:05
Score: 0.5
Natty:
Report link

This issue still alive. I couldn't find any solution on SwiftUI but there is an workaround which can change animation type and duration. This workaround work with introspect and UIKit. You can change simple math calculation or anchor padding according to your case.

Sample code

import SwiftUI
import UIKit
import SwiftUIIntrospect

class ViewModel {
var scrollView: UIScrollView?
let anchorPadding: CGFloat = 60
private let itemHeight: CGFloat = 108 <--- item height(100) + item bottom padding(8)

func scrollTo(id: CGFloat) {
    UIView.animate(
        withDuration: 4.0, <--- You can change animation duration.
        delay: 0.0,
        options: .curveEaseInOut, <--- You can change animation type.
        animations: { [weak self] in
            guard let self else { return }
            scrollView?.contentOffset.y = (itemHeight * id) - anchorPadding <--- Simple math calculation.
        }
    )
  }
}

struct ContentView: View {
private var viewModel = ViewModel()

var body: some View {
    ZStack(alignment: .top) {
        ScrollView {
            VStack(spacing: 8) {
                ForEach(0..<100) { i in
                    Rectangle()
                        .frame(width: 200, height: 100)
                        .foregroundColor(.green)
                        .overlay(Text("\(i)").foregroundColor(.white))
                }
                .frame(maxWidth: .infinity)
            }
        }
        .introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17, .v18)) { scrollView in
            viewModel.scrollView = scrollView  <--- Set current scroll view reference.
        }
        
        Rectangle()
            .fill(.red)
            .frame(maxWidth: .infinity)
            .frame(height: 1)
            .padding(.top, viewModel.anchorPadding)
            .ignoresSafeArea()
            .overlay(alignment: .topTrailing) {
                Button("Scroll To") {
                    viewModel.scrollTo(id: 50) <--- Scroll to item which id is 50.
                }
                .padding(.trailing, 8)
            }
    }
  }
}
Reasons:
  • Blacklisted phrase (1.5): any solution
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (0.5):
Posted by: Okan T.