Как проверить, виден ли элемент — SwiftUI ScrollView

#ios #swiftui #scrollview

#iOS #swiftui #scrollview

Вопрос:

Попытка программно определить, когда элемент отображается на экране в режиме прокрутки в SwiftUI. Я понимаю, что ScrollView отображается одновременно, а не отображается по мере появления элементов (например, в списке), но я ограничен использованием ScrollView, поскольку у меня есть действия .scrollTo .

Я также понимаю, что в UIKit с UIScrollView можно использовать CGRectIntersectsRect между фреймом элемента и фреймом ScrollView в UIScrollViewDelegate, но я бы предпочел найти решение в SwiftUI, если это возможно.

Пример кода выглядит так:

 ScrollView {
    ScrollViewReader { action in
        ZStack {
            VStack {
                ForEach(//array of chats) { chat in
                    //chat display bubble
                        .onAppear(perform: {chatsOnScreen.append(chat)})
                }.onReceive(interactionHandler.$activeChat, perform: { _ in
                    //scroll to active chat
                })
            }
        }
    }
}
 

В идеале, когда пользователь прокручивает, он проверяет, какие элементы находятся на экране, и увеличивает вид, чтобы соответствовать самому большому элементу на экране.

Комментарии:

1. Вы можете использовать LazyVStack in ScrollView для запуска onAppear , когда элементы появляются на экране. Для этого требуется iOS 14.

Ответ №1:

При использовании VStack ScrollView все содержимое создается сразу во время сборки, поэтому onAppear оно не соответствует вашим намерениям, вместо этого вы должны использовать LazyVStack , который будет создавать каждое подпредставление только до его появления на экране, поэтому onAppear будет вызываться, когда вы этого ожидаете.

Так что это должно быть похоже

 ScrollViewReader { action in
   ScrollView {
        LazyVStack {                              // << this !!
            ForEach(//array of chats) { chat in
                //chat display bubble
                    .onAppear(perform: {chatsOnScreen.append(chat)})
            }.onReceive(interactionHandler.$activeChat, perform: { _ in
                //scroll to active chat
            })
        }
    }
}
 

Комментарии:

1. Спасибо. Это будет работать при прокрутке вниз в первый раз, но когда пользователь прокручивает назад, эти чаты уже будут отображаться, и масштабирование не будет обновляться, не так ли?

2. Не определяет, находится ли представление на экране, просто если ОС считает, что оно будет отображаться на экране, и поэтому может быть запущено задолго до появления представления на экране, даже если вы прокрутите назад, и представление никогда не будет показано.