You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现UIView中视频切换及滑动触发下一个视频播放?

Great job getting your first video playing without controls! Adding swipe-to-switch functionality is a common next step, and using a UICollectionView is the cleanest approach here—it natively supports horizontal scrolling and cell reuse, which is perfect for managing multiple videos efficiently.

Let’s break down how to implement this step by step, building on your existing code:


1. Prepare Your Video Data Source

First, create an array to hold your video filenames (this makes it easy to add/remove videos later):

let videoFiles = ["jordanreel", "summer_vacation", "workout_clips"] // Replace with your actual video names

2. Set Up UICollectionView for Horizontal Scrolling

Add a UICollectionView to your storyboard (instead of the single videoView), then link it to an IBOutlet in your view controller:

@IBOutlet weak var videoCollectionView: UICollectionView!

In viewDidLoad, configure the collection view for full-screen, paged horizontal scrolling:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Configure horizontal layout
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .horizontal
    layout.itemSize = view.bounds.size // Each cell fills the screen
    layout.minimumLineSpacing = 0
    
    videoCollectionView.collectionViewLayout = layout
    videoCollectionView.dataSource = self
    videoCollectionView.delegate = self
    videoCollectionView.isPagingEnabled = true // Smooth page-by-page swipes
}

3. Create a Reusable Video Player Cell

Make a custom UICollectionViewCell to encapsulate video playback logic—this ensures proper reuse and avoids memory leaks:

import UIKit
import AVKit

class VideoPlayerCell: UICollectionViewCell {
    var player: AVPlayer?
    private var playerController: AVPlayerViewController!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupPlayerController()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupPlayerController()
    }
    
    private func setupPlayerController() {
        playerController = AVPlayerViewController()
        playerController.showsPlaybackControls = false
        playerController.view.frame = bounds
        addSubview(playerController.view)
        
        // Listen for video finish events (if you want auto-switch after playback)
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(videoDidFinishPlaying),
            name: .AVPlayerItemDidPlayToEndTime,
            object: nil
        )
    }
    
    // Configure cell with a video file
    func configure(with videoName: String) {
        guard let filePath = Bundle.main.path(forResource: videoName, ofType: "mp4"),
              let fileURL = URL(fileURLWithPath: filePath) else { return }
        
        player = AVPlayer(url: fileURL)
        playerController.player = player
        player?.play()
    }
    
    // Pause playback (for when cell is off-screen)
    func pausePlayback() {
        player?.pause()
    }
    
    // Resume playback (for when cell comes on-screen)
    func resumePlayback() {
        player?.play()
    }
    
    @objc private func videoDidFinishPlaying() {
        // Notify parent view controller to switch to next video
        NotificationCenter.default.post(name: .videoPlaybackCompleted, object: self)
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        player?.pause()
        player = nil
        playerController.player = nil
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

// Custom notification name for video finish
extension Notification.Name {
    static let videoPlaybackCompleted = Notification.Name("VideoPlaybackCompleted")
}

4. Implement Collection View DataSource & Delegate

Add these extensions to your view controller to populate the collection view and handle state changes when swiping:

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return videoFiles.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VideoPlayerCell", for: indexPath) as! VideoPlayerCell
        cell.configure(with: videoFiles[indexPath.item])
        return cell
    }
}

extension ViewController: UICollectionViewDelegate {
    // Handle playback state when swiping stops
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let currentIndex = Int(videoCollectionView.contentOffset.x / videoCollectionView.bounds.width)
        
        // Only play the currently visible cell's video
        for cell in videoCollectionView.visibleCells as! [VideoPlayerCell] {
            if let indexPath = videoCollectionView.indexPath(for: cell), indexPath.item == currentIndex {
                cell.resumePlayback()
            } else {
                cell.pausePlayback()
            }
        }
    }
}

5. Add Auto-Switch on Video Finish (Optional)

If you want the app to automatically swipe to the next video when playback ends, add this to your view controller's viewDidLoad:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleVideoFinish),
    name: .videoPlaybackCompleted,
    object: nil
)

Then implement the handler:

@objc private func handleVideoFinish() {
    let currentIndex = Int(videoCollectionView.contentOffset.x / videoCollectionView.bounds.width)
    let nextIndex = currentIndex + 1
    
    // Loop back to first video if we're at the end
    let targetIndex = nextIndex < videoFiles.count ? nextIndex : 0
    let targetPath = IndexPath(item: targetIndex, section: 0)
    
    videoCollectionView.scrollToItem(at: targetPath, at: .centeredHorizontally, animated: true)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

Quick Setup Notes

  • Don’t forget to set your custom cell’s reuse identifier to VideoPlayerCell in the storyboard.
  • Test for edge cases: what if a video file is missing? Add error handling in the configure method to avoid crashes.
  • For better performance, consider pausing off-screen videos immediately (the code above does this, but you can refine it further).

内容的提问来源于stack exchange,提问作者SuperTechy123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:17:32