SwiftUI: Layout & Interfaces

Nov 18 2021 · Swift 5.5, iOS 15, Xcode 13

Part 1: Dynamic View Layout

03. ScrollViewReader

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 02. Lazy Stacks Next episode: 04. Challenge: Nested Scrolling Stacks

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 03. ScrollViewReader

Update Notes: This course was originally recorded in 2020. It has been reviewed and all content and materials updated as of October 2021.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

As you witnessed in the previous episode, sometimes, you’re going to have scrollviews with a TON of children to scroll through. And, maybe, your users would like to access a view that’s somewhere deep into the recesses of your collection.

var body: some View {
    ScrollViewReader { proxy in
      /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Code@*/Text("Placeholder")/*@END_MENU_TOKEN@*/
    }
    ScrollView {
    ScrollViewReader { proxy in
      ScrollView {
        LazyVStack {
          ForEach(Genre.list) { genre in
            genre.subgenres.randomElement()!.view
          }
        }
      }
    }
    ScrollView {
      ScrollViewReader { proxy in
struct ContentView: View {
  @State private var selectedGenre

  var body: some View {
  @State private var selectedGenre = Genre.list.first
          ForEach(Genre.list) { genre in
            genre.subgenres.randomElement()!.view
          }
        }
        .onChange(of: /*@START_MENU_TOKEN@*/"Value"/*@END_MENU_TOKEN@*/) { value in
          /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Code@*/ /*@END_MENU_TOKEN@*/
        }
.onChange(of: selectedGenre) { value in
        .onChange(of: selectedGenre) { value in
          proxy.scrollTo(<#T##id: Hashable##Hashable#>)
        }
        .onChange(of: selectedGenre) {
          proxy.scrollTo($0)
        }
            genre.subgenres.randomElement()!.view
              .id(genre)
          }
proxy.scrollTo($0, anchor: .)
proxy.scrollTo($0, anchor: .top)
    NavigationView {
      ScrollView {
      }
      .navigationBarTitleDisplayMode(.inline)
    }
      .navigationBarTitleDisplayMode(.inline)
      .toolbar {
        /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Content@*/Text("Placeholder")/*@END_MENU_TOKEN@*/
      }
      .toolbar {
        ToolbarItem {

        }
      }
        ToolbarItem {
          Menu("Genre") {

          }
        }
          Menu("Genre") {
            ForEach(Genre.list) { genre in

            }
          }
            ForEach(Genre.list) { genre in
              Button(genre.name) {

              }
            }
              Button(genre.name) {
                selectedGenre = genre
              }
            selectedGenre = nil
            proxy.scrollTo($0, anchor: .top)
            withAnimation {
              proxy.scrollTo($0, anchor: .top)
            }
.onChange(of: selectedGenre) { genre in
proxy.scrollTo(genre, anchor: .top)
proxy.scrollTo(genre)