VisibilityDetector

샤워실의 바보·2024년 2월 11일
0
post-thumbnail
post-custom-banner

visibility_detector 패키지는 Flutter 앱에서 위젯의 가시성 변화를 감지할 수 있게 해주는 도구입니다. 이 패키지를 사용하면 특정 위젯이 화면에 표시되거나, 화면에서 사라질 때를 정확하게 알 수 있으며, 이에 따른 작업을 실행할 수 있습니다.

기능과 사용법:

기능:

  • 위젯이 사용자의 화면에 부분적으로 또는 완전히 보이게 될 때 이를 감지합니다.
  • 위젯의 가시성 비율을 계산하여, 얼마나 많은 부분이 화면에 보이는지 알려줍니다.
  • 위젯이 화면에서 사라질 때 이를 감지합니다.

사용법:
1. visibility_detector 패키지를 프로젝트의 pubspec.yaml 파일에 의존성으로 추가합니다.
2. 필요한 곳에서 패키지를 임포트합니다: import 'package:visibility_detector/visibility_detector.dart';
3. VisibilityDetector 위젯을 사용하여 감지하고 싶은 위젯을 감싸줍니다.
4. VisibilityDetectorkeyonVisibilityChanged 콜백을 설정합니다. onVisibilityChanged 콜백은 위젯의 가시성이 변할 때 호출됩니다.
5. 콜백 함수 내에서, 위젯의 가시성 변화에 따라 필요한 작업을 수행합니다.

예시 코드:

VisibilityDetector(
  key: Key('unique-key'),
  onVisibilityChanged: (VisibilityInfo info) {
    var visiblePercentage = info.visibleFraction * 100;
    print('Widget is ${visiblePercentage}% visible');
  },
  child: YourWidget(), // 감지하고 싶은 위젯
)

이 예시에서는 YourWidget이 화면에 얼마나 보이는지를 백분율로 계산하여 콘솔에 출력합니다. unique-key는 각 VisibilityDetector 인스턴스를 구별하기 위한 고유한 식별자입니다.

주요 사용 사례:

  • 성능 최적화: 화면에 보이지 않는 위젯의 애니메이션을 일시 중지하여 리소스를 절약할 수 있습니다.
  • 사용자 분석: 사용자가 어떤 콘텐츠를 더 많이 보는지 분석하기 위해 사용할 수 있습니다.
  • 동적 로딩: 사용자가 스크롤하여 콘텐츠가 화면에 나타날 때 추가 데이터를 로딩하는 데 사용할 수 있습니다.

visibility_detector 패키지는 Flutter 앱에서 위젯의 가시성을 효과적으로 관리하고, 이를 기반으로 다양한 기능을 구현할 수 있게 해주는 강력한 도구입니다.

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:tiktok_clone/constants/sizes.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';

class VideoPost extends StatefulWidget {
  final Function onVideoFinished;

  final int index;

  const VideoPost({
    super.key,
    required this.onVideoFinished,
    required this.index,
  });

  
  State<VideoPost> createState() => _VideoPostState();
}

class _VideoPostState extends State<VideoPost> {
  final VideoPlayerController _videoPlayerController =
      VideoPlayerController.asset("assets/videos/video.mp4");

  void _onVideoChange() {
    if (_videoPlayerController.value.isInitialized) {
      if (_videoPlayerController.value.duration ==
          _videoPlayerController.value.position) {
        widget.onVideoFinished();
      }
    }
  }

  void _initVideoPlayer() async {
    await _videoPlayerController.initialize();

    setState(() {});
    _videoPlayerController.addListener(_onVideoChange);
  }

  
  void initState() {
    super.initState();
    _initVideoPlayer();
  }

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

  void _onVisibilityChanged(VisibilityInfo info) {
    if (info.visibleFraction == 1 && !_videoPlayerController.value.isPlaying) {
      _videoPlayerController.play();
    }
  }

  void _onTogglePause() {
    if (_videoPlayerController.value.isPlaying) {
      _videoPlayerController.pause();
    } else {
      _videoPlayerController.play();
    }
  }

  
  Widget build(BuildContext context) {
    return VisibilityDetector(
      key: Key("${widget.index}"),
      onVisibilityChanged: _onVisibilityChanged,
      child: Stack(
        children: [
          Positioned.fill(
            child: _videoPlayerController.value.isInitialized
                ? VideoPlayer(_videoPlayerController)
                : Container(
                    color: Colors.black,
                  ),
          ),
          Positioned.fill(
            child: GestureDetector(
              onTap: _onTogglePause,
            ),
          ),
          const Positioned.fill(
            child: IgnorePointer(
              child: Center(
                child: FaIcon(
                  FontAwesomeIcons.play,
                  color: Colors.white,
                  size: Sizes.size52,
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

이 코드는 VisibilityDetector 패키지를 사용하여 Flutter에서 비디오 포스트를 처리하는 방법을 보여줍니다. 특히, 사용자가 스크롤하여 비디오가 화면에 완전히 보이게 될 때 자동으로 재생을 시작하고, 비디오 재생이 끝나면 특정 작업(예: 콜백 함수 실행)을 수행하는 로직을 포함하고 있습니다.

주요 구성 요소 및 로직:

  1. VideoPlayerController:

    • _videoPlayerController는 비디오 파일을 재생하기 위해 사용됩니다. 여기서는 로컬 에셋에서 비디오 파일("assets/videos/video.mp4")을 로드합니다.
  2. _initVideoPlayer 메서드:

    • 비디오 플레이어 컨트롤러를 초기화하고, 비디오 상태 변경(예: 재생 완료) 감지를 위한 리스너를 추가합니다.
  3. _onVideoChange 메서드:

    • 비디오 재생 상태가 변경될 때 호출되는 콜백입니다. 비디오 재생이 완료되면(_videoPlayerController.value.duration == _videoPlayerController.value.position), widget.onVideoFinished 콜백을 실행합니다.
  4. VisibilityDetector:

    • VisibilityDetector 위젯은 비디오 포스트의 가시성을 감지합니다. 각 비디오 포스트에 고유한 key를 할당하여, 스크롤 시 각 포스트의 가시성을 독립적으로 추적할 수 있습니다.
  5. _onVisibilityChanged 메서드:

    • 비디오 포스트의 가시성이 변경될 때 호출됩니다. 만약 비디오가 화면에 100% 가시적일 때(info.visibleFraction == 1) 비디오가 현재 재생되고 있지 않다면(!_videoPlayerController.value.isPlaying), 비디오 재생을 시작합니다.
  6. _onTogglePause 메서드:

    • 사용자가 비디오 위에 탭할 때 호출되는 메서드입니다. 비디오가 재생 중이면 일시 정지하고, 일시 정지 상태면 재생을 시작합니다.
  7. Widget Tree:

    • Stack 위젯을 사용하여 비디오 플레이어, 제스처 감지기, 재생 아이콘을 포함합니다. Positioned.fill을 사용하여 이러한 위젯들이 전체 스택을 채우도록 합니다.
    • IgnorePointer는 사용자 인터페이스에서 특정 위젯(여기서는 재생 아이콘)이 포인터(예: 탭) 이벤트를 받지 않도록 합니다.

결론:

이 코드는 VisibilityDetector를 활용하여 사용자의 스크롤 동작에 따라 비디오 포스트의 재생과 일시 정지를 자동으로 제어합니다. 이를 통해 사용자 경험을 향상시키고, 앱의 성능을 최적화할 수 있습니다. 사용자가 화면에 보이는 비디오만 재생함으로써 리소스 사용을 최적화하고, 불필요한 데이터 로딩을 줄일 수 있습니다.

profile
공부하는 개발자
post-custom-banner

0개의 댓글