PageView.builder, PageController

샤워실의 바보·2024년 2월 10일
0
post-thumbnail
import 'package:flutter/material.dart';
import 'package:tiktok_clone/features/videos/widgets/video_post.dart';

class VideoTimelineScreen extends StatefulWidget {
  const VideoTimelineScreen({super.key});

  
  State<VideoTimelineScreen> createState() => _VideoTimelineScreenState();
}

class _VideoTimelineScreenState extends State<VideoTimelineScreen> {
  int _itemCount = 4;

  final PageController _pageController = PageController();
  final Duration _scrollDuration = const Duration(milliseconds: 250);
  final Curve _scrollCurve = Curves.linear;

  void _onPageChanged(int page) {
    _pageController.animateToPage(
      page,
      duration: _scrollDuration,
      curve: _scrollCurve,
    );
    // page가 _itemCount보다 1 적다면, _itemCount를 4개 더한다. (무한 스크롤)
    if (page == _itemCount - 1) {
      _itemCount = _itemCount + 4;
      setState(() {});
    }
  }

  void _onVideoFinished() {
    _pageController.nextPage(
      duration: _scrollDuration,
      curve: _scrollCurve,
    );
  }

  
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  Future<void> _onRefresh() {
    return Future.delayed(
      const Duration(seconds: 5),
    );
  }

  
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: _onRefresh,
      displacement: 50,
      edgeOffset: 20,
      color: Theme.of(context).primaryColor,
      child: PageView.builder(
        controller: _pageController,
        scrollDirection: Axis.vertical,
        onPageChanged: _onPageChanged,
        itemCount: _itemCount,
        itemBuilder: (context, index) => VideoPost(
          onVideoFinished: _onVideoFinished,
          index: index,
        ),
      ),
    );
  }
}

이 코드는 VideoTimelineScreen이라는 위젯을 정의하고 있습니다. 이 위젯의 주 목적은 수직 방향으로 스크롤하는 PageView 위젯을 표시하는 것입니다.

  1. 상태 변수

    • _itemCount: 현재 표시된 페이지 수를 나타냅니다. 초기에는 4로 설정됩니다.
    • colors: 각 페이지의 배경색을 나타내는 색상 리스트입니다.
  2. _onPageChanged 함수

    • 사용자가 마지막 페이지까지 스크롤하면 _itemCount를 4 증가시키고, colors 리스트에 색상을 추가합니다. 이로써 무한 스크롤 효과가 생깁니다.
  3. build 함수

    • PageView.builder를 사용하여 수직 방향으로 스크롤하는 페이지 뷰를 생성합니다.
    • onPageChanged: 페이지가 변경될 때마다 _onPageChanged 함수가 호출됩니다.
    • itemBuilder: 각 페이지를 빌드하는 함수입니다. 여기서 각 페이지는 colors 리스트의 색상으로 채워진 컨테이너와, 그 안에 중앙에 페이지 번호를 표시하는 텍스트 위젯으로 구성됩니다.

이 위젯은 사용자가 수직으로 스크롤하면서 각각 다른 배경색을 가진 페이지를 볼 수 있습니다. 사용자가 마지막 페이지에 도달하면 추가 페이지가 자동으로 로드되어 무한 스크롤 효과가 나타납니다.

video_timeline_screen.dart 파일은 TikTok 앱에서 비디오 타임라인 화면을 구성하는 코드가 포함된 파일입니다. 이 파일에서는 RefreshIndicator 위젯과 PageView.builder 위젯을 사용하여 화면을 구성합니다.

RefreshIndicator 위젯은 화면을 아래로 당겨서 새로고침하는 기능을 제공하는 위젯입니다. onRefresh 속성을 사용하여 새로고침 이벤트를 처리합니다. displacement 속성과 edgeOffset 속성을 사용하여 새로고침 인디케이터의 위치를 설정합니다. color 속성을 사용하여 새로고침 인디케이터의 색상을 설정합니다.

PageView.builder

PageView.builder 위젯은 여러 개의 페이지를 스크롤하여 보여주는 데 사용됩니다. controller 속성을 사용하여 페이지 컨트롤러를 설정합니다. scrollDirection 속성을 사용하여 스크롤 방향을 vertical로 설정합니다. onPageChanged 속성을 사용하여 페이지가 변경될 때의 이벤트를 처리합니다. itemCount 속성을 사용하여 페이지의 개수를 설정합니다. itemBuilder 속성을 사용하여 페이지를 구성하는 위젯을 설정합니다.

VideoPost 위젯은 비디오 포스트를 구성하는 위젯입니다. onVideoFinished 속성을 사용하여 비디오 재생이 완료될 때의 이벤트를 처리합니다. index 속성을 사용하여 페이지의 인덱스를 설정합니다.

_onPageChanged 함수에서는 페이지가 마지막 페이지에 도달하면 _itemCount 변수를 4 증가시키고, 화면을 다시 그리도록 setState 함수를 호출합니다. 이를 통해 페이지가 무한히 스크롤되도록 구현할 수 있습니다.

_onVideoFinished 함수에서는 페이지 컨트롤러의 nextPage 메서드를 호출하여 다음 페이지로 이동합니다.

_onRefresh 함수에서는 5초 후에 새로고침 이벤트를 처리합니다. 이를 통해 새로운 비디오 포스트를 가져오는 등의 작업을 수행할 수 있습니다.

PageController

이 두 함수는 VideoTimelineScreen에서 비디오 재생과 관련하여 페이지 뷰의 동작을 제어하기 위해 사용됩니다. 각 함수에 대한 설명은 다음과 같습니다:

  1. _onPageChanged 함수:

    • 매개변수: int page - 현재 활성화된 페이지의 인덱스.
    • 동작:
      • 먼저, _pageController.animateToPage를 사용하여 페이지 뷰를 지정된 페이지로 부드럽게 스크롤합니다. 이는 사용자가 페이지를 직접 스크롤하였을 때 이 스크롤 동작을 부드럽게 애니메이션 처리하기 위한 것입니다. 여기서는 durationcurve를 이전에 정의한 _scrollDuration_scrollCurve로 설정하여 애니메이션의 지속시간과 방식을 정의합니다.
      • 만약 현재 페이지가 마지막 페이지 (_itemCount - 1)라면, _itemCount를 4만큼 증가시키고 상태를 갱신합니다. 이렇게 함으로써, 추가적인 비디오 항목들을 로드할 준비를 합니다.
  2. _onVideoFinished 함수:

    • 이 함수는 현재 비디오 재생이 완료되었을 때 호출됩니다.
    • 동작:
      • _pageController.nextPage를 사용하여 페이지 뷰를 다음 페이지로 부드럽게 스크롤합니다. 여기서도 애니메이션의 지속시간과 방식은 이전에 정의한 _scrollDuration_scrollCurve를 사용합니다.

간단히 말하면, _onPageChanged는 사용자가 직접 페이지를 스크롤했을 때 동작하며, _onVideoFinished는 비디오 재생이 끝났을 때 자동으로 다음 페이지로 전환하기 위해 동작합니다.

import 'package:flutter/material.dart';

class VideoTimelineScreen extends StatefulWidget {
  const VideoTimelineScreen({super.key});

  
  State<VideoTimelineScreen> createState() => _VideoTimelineScreenState();
}

class _VideoTimelineScreenState extends State<VideoTimelineScreen> {
  int _itemCount = 4;

  List<Color> colors = [
    Colors.blue,
    Colors.red,
    Colors.yellow,
    Colors.teal,
  ];

  void _onPageChanged(int page) {
    if (page == _itemCount - 1) {
      _itemCount = _itemCount + 4;
      colors.addAll([
        Colors.blue,
        Colors.red,
        Colors.yellow,
        Colors.teal,
      ]);
      setState(() {});
    }
  }

  
  Widget build(BuildContext context) {
    return PageView.builder(
      scrollDirection: Axis.vertical,
      onPageChanged: _onPageChanged,
      itemCount: _itemCount,
      itemBuilder: (context, index) => Container(
        color: colors[index],
        child: Center(
          child: Text(
            "Screen $index",
            style: const TextStyle(fontSize: 68),
          ),
        ),
      ),
    );
  }
}

이 Flutter 코드는 PageView.builder를 사용하여 수직 방향으로 스크롤할 수 있는 페이지를 생성하는 예제입니다. 사용자가 마지막 페이지에 도달할 때마다, 추가 페이지가 동적으로 생성되며, 각 페이지는 다른 색상과 텍스트를 표시합니다.

비지니스 로직의 핵심 요소:

  1. _itemCount:

    • _itemCount 변수는 현재 페이지 뷰에 몇 개의 페이지가 있는지 추적합니다. 초기 값은 4입니다.
  2. colors 리스트:

    • colors 리스트는 각 페이지의 배경색을 저장합니다. 초기에는 4가지 색상이 설정됩니다.
  3. _onPageChanged 메서드:

    • _onPageChanged 메서드는 페이지가 변경될 때 호출되며, PageView.builderonPageChanged 콜백으로 설정됩니다.
    • 사용자가 마지막 페이지에 도달하면(즉, page == _itemCount - 1일 때), _itemCount를 4만큼 증가시키고, colors 리스트에 추가 색상을 추가합니다.
    • setState()를 호출하여 변경사항을 적용하고 UI를 업데이트합니다.
  4. PageView.builder:

    • PageView.builder는 수직 방향으로 스크롤할 수 있는 페이지 뷰를 생성합니다(scrollDirection: Axis.vertical).
    • itemBuilder 콜백은 각 페이지를 생성할 때 호출되며, 페이지의 배경색과 중앙에 표시될 텍스트를 설정합니다.
    • itemCount는 현재 페이지의 총 수를 결정합니다.

비지니스 로직의 흐름:

  1. 앱이 시작되면, 4개의 페이지가 PageView.builder에 의해 생성됩니다. 각 페이지는 colors 리스트에 정의된 색상 중 하나로 배경색이 설정됩니다.
  2. 사용자가 페이지를 스크롤하여 마지막 페이지에 도달하면, _onPageChanged 메서드가 실행됩니다.
  3. _onPageChanged 내부에서, _itemCount가 4만큼 증가하고, colors 리스트에 같은 4가지 색상이 다시 추가됩니다. 이는 무한 스크롤과 같은 사용자 경험을 제공합니다.
  4. setState() 호출로 인해 PageView.builder가 다시 빌드되고, 새로운 페이지들이 UI에 반영됩니다.

결론:

이 코드는 동적인 무한 스크롤 페이지 뷰를 구현하는 방법을 보여줍니다. 사용자가 스크롤을 계속할 수록, 페이지 수가 증가하며 새로운 콘텐츠가 계속해서 제공됩니다. 이러한 패턴은 사용자가 콘텐츠를 탐색할 때 추가 로딩 시간 없이 끊임없는 스크롤 경험을 제공하는 데 유용합니다.

profile
공부하는 개발자

0개의 댓글