MMPlayerView
Demo-Swift
List / Shrink / Transition / Landscape
MMPlayerLayer
ex. use when change player view frequently like tableView / collectionView
import MMPlayerView
mmPlayerLayer.playView = cell.imgView
mmPlayerLayer.getStatusBlock { [weak self] (status) in
}
self.mmPlayerLayer.set(url: DemoSource.shared.demoData[indexPath.row].play_Url)
self.mmPlayerLayer.resume()
Transition
##PresentedViewController
1. Set transition config
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.mmPlayerTransition.present.pass { (config) in
// setting
.....
}
}
2. Set MMPLayerToProtocol on PresentedViewController
3. Set MMPlayerPrsentFromProtocol on PresentingViewController
Landscape
1.Set MMPlayerLayer
// roation screen to landscape can change player to fullscreen
mmplayerLayer.fullScreenWhenLandscape = true
2. Set from code
mmplayerLayer.setOrientation(.landsacpeLeft)
3. Observer
mmPlayerLayer.getOrientationChange { (status) in
print("Player OrientationChange \(status)")
}
Cover View
## add cover item view on player
play.replace(cover: CoverA.instantiateFromNib())
Progress
// Custom your progress view and it will add on player center
// view need to implement ProgressProtocol, and add progress in this view, when start/stop control what need to do
.custom(view: <#T##MMProgressProtocol#>)
public protocol MMProgressProtocol {
func start()
func stop()
}
Cache
playerLayer.cacheType = .memory(count: 10)
public enum MMPlayerCacheType {
case none
case memory(count: Int) // set this to cache seek time in memory and if cache out of count will remove first you
stored
}
Layer Protocol
// detect if touch in videoRect
// if touch out of videoRect will not trigger show/hide cover view event
public protocol MMPlayerLayerProtocol: class {
func touchInVideoRect(contain:
) //
}
Downloader
var downloadObservation: MMPlayerObservation?
downloadObservation = MMPlayerDownloader.shared.observe(downloadURL: downloadURL) { [weak self] (status) in
switch status {
case .cancelled:
print("Canceld")
case .completed:
DispatchQueue.main.async {
self?.downloadBtn.setTitle("Delete", for: .normal)
self?.downloadBtn.isHidden = false
self?.progress.isHidden = true
}
case .downloading(let value):
self?.downloadBtn.isHidden = true
self?.progress.isHidden = false
self?.progress.progress = value
print("Exporting \(value) \(downloadURL)")
case .failed(let err):
DispatchQueue.main.async {
self?.downloadBtn.setTitle("Download", for: .normal)
}
self?.downloadBtn.isHidden = false
self?.progress.isHidden = true
print("Download Failed \(err)")
case .none:
DispatchQueue.main.async {
self?.downloadBtn.setTitle("Download", for: .normal)
}
self?.downloadBtn.isHidden = false
self?.progress.isHidden = true
case .exist:
DispatchQueue.main.async {
self?.downloadBtn.setTitle("Delete", for: .normal)
}
self?.downloadBtn.isHidden = false
self?.progress.isHidden = true
}
Delete
if let info = MMPlayerDownloader.shared.localFileFrom(url: downloadURL) {
MMPlayerDownloader.shared.deleteVideo(info)
}
Subtitle
let subTitleStr = Bundle.main.path(forResource: "test", ofType: "srt")!
if let str = try? String.init(contentsOfFile: subTitleStr) {
self.mmPlayerLayer.subtitleSetting.subtitleType = .srt(info: str)
self.mmPlayerLayer.subtitleSetting.defaultTextColor = .red
self.mmPlayerLayer.subtitleSetting.defaultFont = UIFont.boldSystemFont(ofSize: 20)
}
}
Shrink
// Return a view which you want back
self.mmPlayerLayer.shrinkView(onVC: self, isHiddenVC: false) { [weak self] () -> UIView? in
guard let self = self, let path = self.findCurrentPath() else {return nil}
let cell = self.findCurrentCell(path: path) as! PlayerCell
self.mmPlayerLayer.set(url: cell.data!.play_Url)
self.mmPlayerLayer.resume()
return cell.imgView
}
// Check player is shrink or not
self.mmPlayerL.isShrink
Demo-SwiftUI
Control
let control = MMPlayerControl()
//Play
control.set(url: self.videoList[idx].play_Url)
control.resume()
//InValidate
control.invalidate()
//Observation parameter
@Published
public var orientation: PlayerOrientation = .protrait
@Published
public var timeInfo = TimeInfo()
@Published
public var isMuted = false
@Published
public var isBackgroundPause = true
@Published
@Published
public var repeatWhenEnd: Bool = false
@Published
public var isLoading: Bool = false
public var cacheType: PlayerCacheType = .none
@Published
public private(set) var isCoverShow = false
@Published
public var autoHideCoverType = CoverAutoHideType.disable
public var coverAnimationInterval = 0.3
@Published
public var error: MMPlayerViewUIError?
Init View
let player = MMPlayerViewUI(control: self.control, cover: CoverAUI())
Download
view.modifier(MMPlayerDownloaderModifier(url: obj.play_Url!, status: $downloadStatus))
Transition Player
//func playerTransition<Content: View>(view: Content, from: CGRect?) -> AnyTransition
if showDetailIdx != nil {
DetailView(obj: self.playListViewModel.videoList[showDetailIdx!], showDetailIdx: $showDetailIdx)
.edgesIgnoringSafeArea(.all)
.transition(.playerTransition(view: MMPlayerViewUI(control: control) ,from: fromFrame))
.zIndex(1)
}
// Trigger transition
withAnimation {
self.fromFrame = obj.frame
self.showDetailIdx = offset
}
Requirements
iOS 12.0+
Swift 5.0+
Installation
MMPlayerView is available through CocoaPods. To install it, simply add the following line to your Podfile:
Swift 5
pod 'MMPlayerView'Author
License
MMPlayerView is available under the MIT license. See the LICENSE file for more info.

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.







