ScrollViewReader scrollTo scrolling too much on iOS 15

374 views Asked by At

On iOS 15 there is an issue with scrollTo of ScrollViewReader, it is scrolling too much. I have a button and a date picker, when tapping the button I show the date picker but I want to make sure the date picker is fully visible on the screen, so I scroll to it. The code to reproduce the issue is attached below:

import SwiftUI

struct ScrollToIssue: View {
    @State var showPicker: Bool = false
    @State var date: Date = Date()
    
    var body: some View {
        ScrollViewReader { scrollViewReader in
            ScrollView {
                
                Color.red.frame(height: 400)
                
                Color.yellow.frame(height: 200)
                
                VStack {
                    Button(action: {
                        showPicker.toggle()
                        
                        if showPicker {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                                withAnimation {
                                    scrollViewReader.scrollTo("pickerrrr")
                                }
                            })
                        }
                    }, label: {
                        Text("Show picker")
                    })
                    
                    if showPicker {
                        DatePicker(selection: $date,
                                   displayedComponents: .date,
                                   label: { EmptyView() })
                        .labelsHidden()
                        .datePickerStyle(GraphicalDatePickerStyle())
                        .id("pickerrrr")
                    }
                }
                .border(Color.green)
                
                Color.blue.frame(height: 500)
            }
        }
    }
}

On iOS 16/17, is working fine. Also tried to move the ScrollViewReader inside/outside of ScrollView, makes no difference, also tried with anchor .bottom, still same issue.

I used Xcode 15.0 with Iphone 13, iOS 15.5

1

There are 1 answers

0
Cheolhyun On

I believe this is a bug in SwiftUI.

There are many other people who have already encountered the same issue. https://developer.apple.com/forums/thread/688230

Anyway, you can avoid this issue by using LazyVStack instead of VStack.

Notes: I haven't updated my macOS yet, so I'm using Xcode 14.3, so I haven't tested it against iOS 17.

struct ScrollToIssue: View {
  @State var showPicker: Bool = false
  @State var date: Date = Date()
  
  var body: some View {
    ScrollViewReader { scrollViewReader in
      ScrollView {
        
        Color.red.frame(height: 400)
        
        Color.yellow.frame(height: 200)
        
        LazyVStack {  //  Instead of VStack
          Button(action: {
            showPicker.toggle()
            
            if showPicker {
              DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                withAnimation {
                  scrollViewReader.scrollTo("pickerrrr")
                }
              })
            }
          }, label: {
            Text("Show picker")
          })
          
          if showPicker {
            DatePicker(selection: $date,
                       displayedComponents: .date,
                       label: { EmptyView() })
            .labelsHidden()
            .datePickerStyle(GraphicalDatePickerStyle())
            .id("pickerrrr")
          }
        }
        .border(Color.green)
        
        Color.blue.frame(height: 500)
      }
    }
  }
}