inflearn logo
강의

講義

知識共有

[コードファクトリー] [初級] Flutter 3.0 アプリ開発 - 10個のプロジェクトで今日、初心者脱出!

Video Player 프로젝트에 대한 추가 질문

53

Ryu

投稿した質問数 4

0

선생님 강의 너무 잘 듣고 있습니다.

video_player 프로젝트 관련 내용 모두 확인했고, 여기에 하나만 간단하게 비디오에서 나가기 버튼을 추가해보았습니다.

 

일단 제가 작성해본 코드부터 공유하겠습니다.

테스트 상 로고화면으로는 잘 돌아갑니다. _VideoPlayerStatedispose() 함수도 정상적으로 실행돼요.

다만 로직이 실제 앱에서 실행되어도 충분히 괜찮은 로직일지,

혹은 더 안전한 방법이나 기타 필요한 수정사항이 있다면 알려주시면 감사하겠습니다.

 

  1. _HomeScreenState 내부

    class _HomeScreenState extends State<HomeScreen> {
      // bool showVideo = false;
      XFile? video;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.black87,
          body: video == null
              ? _VideoSelector(onLogoTap: openPicker)
              : _VideoPlayer(
                  video: video!,
                  onImageIconPressed: openPicker,
                  onExitIconPressed: exitPlayer, // 나가기 버튼 함수
                ),
        );
      }
    
      void openPicker() async {
        // setState(() => showVideo = true);
    
        /// ImageSource.gallary: 사진 앱에 저장된 이미지/비디오 파일 선택
        /// ImageSource.camera: 디바이스가 즉시 촬영한 이미지/비디오 파일 선택
        const source = ImageSource.gallery;
    
        /// pickVideo(): 사용자 비디오 파일을 선택
        final picked = await ImagePicker().pickVideo(source: source);
        // print(picked);
        setState(() => video = picked);
      }
    
      /// ↓↓ 여기에 비디오에서 나가기 로직 추가
      void exitPlayer() {
        setState(() {
          // print('info: exitIconButton 클릭');
          video = null;
        });
      }
    }  

 

  1. _VideoPlayerState 내부

    class _VideoPlayerState extends State<_VideoPlayer> {
      late VideoPlayerController _videoPlayerController;
      bool showButton = true;
    
      // ...
      
      /// 위젯 상태 제거
      @override
      void dispose() {
        _videoPlayerController.dispose();
        print('info: 비디오 플레이어 종료 중..');
        super.dispose();
      }
      
      @override
      Widget build(BuildContext context) {
        final VideoPlayerValue videoPlayer = _videoPlayerController.value;
        // final position = videoPlayer.position;
        // final duration = videoPlayer.duration;
        return Center(
          child: AspectRatio(
            aspectRatio: videoPlayer.aspectRatio,
            child: GestureDetector(
              onTap: () => setState(() => showButton = !showButton),
              child: Stack(
                children: <Widget>[
                  VideoPlayer(_videoPlayerController),
                  /// 영상 화면 커버
                  if (showButton)
                    Container(
                      width: double.infinity,
                      height: double.infinity,
                      color: Colors.black.withAlpha(128),
                    ),
    
                  /// 재생/중지와 뒤로&앞으로 버튼
                  if (showButton)
                    _PlayButton(
                      isPlaying: videoPlayer.isPlaying,
                      onReversePressed: onReversePressed,
                      onPlayPressed: onPlayPressed,
                      onForwardPressed: onForwardPressed,
                    ),
    
                  /// 하단 슬라이더
                  if (showButton)
                    _BottomSlider(
                      position: videoPlayer.position,
                      duration: videoPlayer.duration,
                      onSliderMoved: onSliderMoved,
                    ),
                  /// 화면 상단 버튼
                  if (showButton)
                    _TopButtons( // ← 여기를 2개의 버튼으로 확장
                      onExitPressed: widget.onExitIconPressed,
                      onImagePressed: widget.onImageIconPressed,
                    ),
                ],
              ),
            ),
          ),
        );
      }

 

  1. _TopButtons 내부

    class _TopButtons extends StatelessWidget {
      final VoidCallback onImagePressed;
      final VoidCallback onExitPressed;
    
      const _TopButtons({
        required this.onExitPressed,
        required this.onImagePressed,
      });
    
      @override
      Widget build(BuildContext context) {
        return Positioned(
          left: 4,
          right: 4,
          top: 0,
          // Row로 감싸고 왼쪽에 '나가기' 버튼 추가
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <IconButton>[
              // 나가기 버튼
              IconButton(
                onPressed: onExitPressed,
                icon: Icon(Icons.chevron_left, color: Colors.white),
              ),
              // 다른 영상 선택 버튼
              IconButton(
                onPressed: onImagePressed,
                icon: Icon(Icons.photo_camera_back, color: Colors.white),
              ),
            ],
          ),
        );
      }
    }

 

 

flutter 클론코딩 video_player

回答 0

198강 (){onTap(e);}의 이해 돕기

0

28

1

video_call 플러그인 설치후 에러 발생

0

46

1

SDK 안드로이드 설치 질문!

0

60

1

코드팩토리 디스코드 링크 다시 부탁드려요~

0

92

1

Webview를 이용해서 URL 상의 페이지 출력 불가

0

70

1

홈스크린 함수를 함축해서 main.dart에 옮기는 문제

0

55

1

플레이스토어

0

59

1

아고라 엔진 init 함수의 반환타입이 Future<void> 이것의 의미는 무엇인가요?

0

55

1

가이드라인 질문

0

57

0

emulator 에러 환경설정 뭐가 문제 일까요??

0

77

1

emulator 실행 오류

0

93

3

Column을 가로방향 최대 사이즈를 차지하도록 하는 방법에 관련

0

71

1

pubspec.yaml에서 font를 추가하면서 weight 값을 지정하는 것이 의미가 있는 것인지 문의

0

43

1

setState()를 호출하지 않으면 build가 실행 안되는 건가요?

0

53

1

video_call 플러그인 설치시 에러문제

0

64

1

children 안의 if 문에서 { } 못쓰는 이유?

0

48

1

이렇게 오류가 떠요

0

64

1

AppBar 사용했는데

0

61

2

[문제해결] '오늘도 출첵!' 의 171번 강의에서 중요한 문제를 발견했습니다

0

56

1

StatefulWidget 실습 에러가 발생합니다.[해결완료]

0

63

1

Row위젯이나 column위젯의 위치는 누가 정하나요??

0

42

1

geolocator 오류때문에 개발진행이 불가능입니다

0

63

1

API 관련 이슈

0

86

2

VoidCallback 뒤에 null 연산자 표기에 관한 질문

0

47

1