Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions PickaView/Views/Player/FullscreenPlayerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class FullscreenPlayerViewController: UIViewController {
/// (옵션) 전체화면 모드 여부
private var isFullscreenMode = false

var exitFullscreenButton: UIButton = UIButton()
var dismissButton: UIButton = UIButton()

// MARK: - Lifecycle

/// 뷰가 메모리에 올라왔을 때 호출
Expand Down Expand Up @@ -66,6 +69,21 @@ class FullscreenPlayerViewController: UIViewController {
])
}

exitFullscreenButton.translatesAutoresizingMaskIntoConstraints = false
exitFullscreenButton.setImage(UIImage(systemName: "arrow.up.forward.and.arrow.down.backward.rectangle"), for: .normal)
exitFullscreenButton.tintColor = .white
exitFullscreenButton.addTarget(self, action: #selector(handleDismiss), for: .touchUpInside)
controlsOverlayView?.addSubview(exitFullscreenButton)

if let overlay = controlsOverlayView {
NSLayoutConstraint.activate([
exitFullscreenButton.trailingAnchor.constraint(equalTo: overlay.trailingAnchor, constant: -16),
exitFullscreenButton.bottomAnchor.constraint(equalTo: overlay.bottomAnchor, constant: -37),
exitFullscreenButton.widthAnchor.constraint(equalToConstant: 25),
exitFullscreenButton.heightAnchor.constraint(equalToConstant: 25)
])
}

// 스와이프 다운 제스처(뷰/오버레이에 모두 등록)
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(handleDismiss))
swipeDown.direction = .down
Expand All @@ -80,6 +98,16 @@ class FullscreenPlayerViewController: UIViewController {
object: nil
)
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
exitFullscreenButton.isHidden = false
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
exitFullscreenButton.isHidden = true
}

/// 레이아웃이 변경될 때마다 AVPlayerLayer 크기 갱신
override func viewDidLayoutSubviews() {
Expand Down
4 changes: 4 additions & 0 deletions PickaView/Views/Player/Player.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<<<<<<< feature/dismiss-fullscreen-btn
<constraint firstAttribute="width" secondItem="K5S-xl-3OB" secondAttribute="height" multiplier="16:9" priority="750" id="Lbo-f3-1RB"/>
=======
<constraint firstItem="DS6-vJ-IHs" firstAttribute="centerX" secondItem="K5S-xl-3OB" secondAttribute="centerX" id="03X-jH-E26"/>
<constraint firstAttribute="width" secondItem="K5S-xl-3OB" secondAttribute="height" multiplier="16:9" id="Lbo-f3-1RB"/>
<constraint firstItem="DS6-vJ-IHs" firstAttribute="top" secondItem="K5S-xl-3OB" secondAttribute="top" constant="30" id="il4-e6-mQM"/>
>>>>>>> dev
</constraints>
</view>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="NV6-1e-jJs">
Expand Down
7 changes: 4 additions & 3 deletions PickaView/Views/Player/PlayerViewController+UI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension PlayerViewController {

// MARK: - UI 초기 세팅

/// UI 컴포넌트 계층 및 오토레이아웃 세팅, 더미 스크롤 컨텐츠 추가
/// UI 컴포넌트 계층 및 오토레이아웃 세팅
func setupUI() {
videoPlayerView.addSubview(videoContainerView)

Expand Down Expand Up @@ -63,7 +63,7 @@ extension PlayerViewController {
seekerStack.trailingAnchor.constraint(equalTo: controlsOverlayView.trailingAnchor, constant: -16),
seekerStack.bottomAnchor.constraint(equalTo: controlsOverlayView.bottomAnchor, constant: -16),

fullscreenButton.bottomAnchor.constraint(equalTo: seekerStack.topAnchor),
fullscreenButton.bottomAnchor.constraint(equalTo: seekerStack.topAnchor, constant: -5),
fullscreenButton.trailingAnchor.constraint(equalTo: controlsOverlayView.trailingAnchor, constant: -16),

dismissButton.topAnchor.constraint(equalTo: controlsOverlayView.topAnchor, constant: 16),
Expand Down Expand Up @@ -128,7 +128,8 @@ extension PlayerViewController {
let imageName = isPlaying ? "pause.fill" : "play.fill"
let img = UIImage(systemName: imageName, withConfiguration: symbolConfig)
playPauseButton.setImage(img, for: .normal)
playPauseButton.imageEdgeInsets = isPlaying ? UIEdgeInsets(top: -8, left: -8, bottom: -8, right: -8) : .zero
playPauseButton.configuration = .plain()
playPauseButton.configuration?.imagePadding = isPlaying ? 8 : 0
}

/// 시간 라벨 생성 (monospaced font)
Expand Down
28 changes: 23 additions & 5 deletions PickaView/Views/Player/PlayerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class PlayerViewController: UIViewController, PlayerViewControllerDelegate {
} else {
print("Invalid video URL")
}

setupUI()
setPlayPauseImage(isPlaying: true)
fullscreenButton.alpha = 1.0
Expand Down Expand Up @@ -207,6 +208,8 @@ class PlayerViewController: UIViewController, PlayerViewControllerDelegate {

navigationController?.setNavigationBarHidden(true, animated: false)
tabBarController?.tabBar.isHidden = true
fullscreenButton.isHidden = false
dismissButton.isHidden = false
}

/// 뷰가 나타날 때 방향/레이아웃 갱신
Expand Down Expand Up @@ -246,6 +249,8 @@ class PlayerViewController: UIViewController, PlayerViewControllerDelegate {

navigationController?.setNavigationBarHidden(false, animated: false)
tabBarController?.tabBar.isHidden = false
fullscreenButton.isHidden = true
dismissButton.isHidden = true
}

// MARK: - Player Controls
Expand Down Expand Up @@ -282,8 +287,16 @@ class PlayerViewController: UIViewController, PlayerViewControllerDelegate {
/// 재생/일시정지 버튼 클릭 핸들러
@objc func playPauseButtonTapped() {
guard let player = self.player else { return }

animateButtonTap(playPauseButton) { [weak self] in
guard let self = self else { return }

if !self.isPlaying,
let player = self.player,
player.currentItem?.currentTime() == player.currentItem?.duration {
player.seek(to: .zero)
}

self.isPlaying.toggle()
self.setPlayPauseImage(isPlaying: self.isPlaying)

Expand Down Expand Up @@ -337,14 +350,19 @@ class PlayerViewController: UIViewController, PlayerViewControllerDelegate {

/// 영상 재생이 끝났을 때 호출됨 (자동 초기화)
@objc func playerDidFinishPlaying() {
guard let player = self.player else { return }
isPlaying = false
viewModel?.pauseWatching()
let playImage = UIImage(systemName: "arrow.clockwise")
let playImage = UIImage(systemName: "arrow.clockwise", withConfiguration: symbolConfig)
playPauseButton.setImage(playImage, for: .normal)
player.seek(to: .zero)
progressSlider.value = 0
currentTimeLabel.text = "00:00"
areControlsVisible = true
cancelControlsHide()

UIView.animate(withDuration: 0.3) {
self.playbackControlsStack.alpha = 1.0
self.seekerStack.alpha = 1.0
self.fullscreenButton.alpha = 1.0
self.dismissButton.alpha = 1.0
}
}

/// 컨트롤 자동 숨김 타이머 재설정
Expand Down