Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni
🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!25.10.2023
Реалізація посторінкової прокрутки на SwiftUI
Проєкт, який я роблю, потребує посторінкової прокрутки на кшталт TikTok. Як виявилось, це не щось легко доступне, та найкраще поки що рішення я зробив сам.
Почав взагалі з найбільш очевидного — є ScrollView, а в нього цього року зʼявився scrollTargetBehavior(.paging). Він робить дещо схоже на CSS scroll-snap-type
, але прокрутка зупинятиметься на кожному екрані. Ніби це те, що потрібно. Але проблем купа:
-
Використання памʼяті. Ми точно не хочемо створювати всі елементи списку відразу. Взагалі, як виявилось зі статей про такі інтерфейси, керування памʼяттю це як не найголовніше; наприклад, забагато відео чи навіть світлин в памʼять не влізе. На то є LazyVStack. Він утворюватиме дочірні елементи тільки тоді, коли до них дійде черга. На перший погляд — те, що треба. Проте як виявилось,
LazyVStack
ніколи не звільняє елементи. Відповідно, з довгим списком все одно буде та сама проблема, тільки пізніше. -
Поведінка при повороті екрана. Оскільки кожний елемент має розміри екрана, то при повороті висота елементу змінюється, а значить, позиція в списку (яка відстежується за координатою) втрачається. Можна це розвʼязати через те, щоб після повороту перемотувати список знову на поточний елемент. На жаль, список перемотується тільки з анімацією — це не тільки некрасиво, а й відстрілює промальовку всіх проміжних елементів.
-
Загальна нестабільність. Посторінкова прокрутка тут це тільки додаткове обмеження, та час від часу вона збивається. Особливо якщо прокручувати за допомогою смуги прокрутки — тоді режим сторінок практично виключається.
Є ще компонент List — він гарно впорається з довгим списком, оскільки реально використовує елементи повторно — взагалі цей компонент краще брати для схожих задач. От тільки List
не вміє робити посторінкову прокрутку.
Найскладніша частина свого рішення — це обробка жестів. Але про це завтра.