1
@ -62,4 +62,8 @@ extension UIColor {
|
||||
static func color5A5D45(alpha: CGFloat = 1) -> UIColor {
|
||||
return UIColor(rgb: 0x5A5D45, alpha: alpha)
|
||||
}
|
||||
|
||||
static func colorFFFDF9(alpha: CGFloat = 1) -> UIColor {
|
||||
return UIColor(rgb: 0xFFFDF9, alpha: alpha)
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,40 @@ class BRExploreViewController: BRPlayerListViewController {
|
||||
return CGSize(width: width, height: height)
|
||||
}
|
||||
|
||||
private lazy var titleImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "explore_title_icon"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var searchButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "search_icon_01"), for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var videoNameLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .fontMedium(ofSize: 12)
|
||||
label.textColor = .colorFFFDF9()
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var episodeButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "episode_icon_01"), for: .normal)
|
||||
button.setContentHuggingPriority(.required, for: .horizontal)
|
||||
button.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var favoriteButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "favorite_icon_02"), for: .normal)
|
||||
button.setContentHuggingPriority(.required, for: .horizontal)
|
||||
button.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
return button
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.edgesForExtendedLayout = .all
|
||||
@ -67,12 +101,44 @@ extension BRExploreViewController {
|
||||
self.collectionView.layer.cornerRadius = 20
|
||||
self.collectionView.layer.masksToBounds = true
|
||||
|
||||
view.addSubview(titleImageView)
|
||||
view.addSubview(searchButton)
|
||||
view.addSubview(episodeButton)
|
||||
view.addSubview(favoriteButton)
|
||||
view.addSubview(videoNameLabel)
|
||||
|
||||
self.collectionView.snp.remakeConstraints { make in
|
||||
make.left.equalToSuperview().offset(15)
|
||||
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 50)
|
||||
make.width.equalTo(contentSize.width)
|
||||
make.height.equalTo(contentSize.height)
|
||||
}
|
||||
|
||||
titleImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(15)
|
||||
make.bottom.equalTo(collectionView.snp.top).offset(-15)
|
||||
}
|
||||
|
||||
searchButton.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(titleImageView)
|
||||
make.right.equalToSuperview().offset(-15)
|
||||
}
|
||||
|
||||
episodeButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-15)
|
||||
make.top.equalTo(collectionView.snp.bottom).offset(10)
|
||||
}
|
||||
|
||||
favoriteButton.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(episodeButton)
|
||||
make.right.equalTo(episodeButton.snp.left).offset(-40)
|
||||
}
|
||||
|
||||
videoNameLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(episodeButton)
|
||||
make.left.equalToSuperview().offset(15)
|
||||
make.right.lessThanOrEqualTo(favoriteButton.snp.left).offset(-25)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -94,6 +160,10 @@ extension BRExploreViewController: BRPlayerListViewControllerDelegate, BRPlayerL
|
||||
func br_playerListViewController(_ viewController: BRPlayerListViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func br_playerListViewController(_ viewController: BRPlayerListViewController, didChangeIndexPathForVisible indexPath: IndexPath) {
|
||||
videoNameLabel.text = self.viewModel.currentPlayer?.shortModel?.name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,6 +88,10 @@ class BRPlayerListViewController: BRViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.statusBarStyle = .lightContent
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActiveNotification), name: UIApplication.didBecomeActiveNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(willResignActiveNotification), name: UIApplication.willResignActiveNotification, object: nil)
|
||||
|
||||
br_setupUI()
|
||||
}
|
||||
|
||||
@ -131,6 +135,11 @@ class BRPlayerListViewController: BRViewController {
|
||||
// }
|
||||
}
|
||||
|
||||
func pause() {
|
||||
self.viewModel.currentPlayer?.pause()
|
||||
self.viewModel.isPlaying = false
|
||||
}
|
||||
|
||||
func reloadData(completion: (() -> Void)? = nil) {
|
||||
|
||||
UIView.performWithoutAnimation {
|
||||
@ -276,6 +285,13 @@ extension BRPlayerListViewController: BRPlayerViewModelDelegate {
|
||||
scrollToNextEpisode()
|
||||
}
|
||||
|
||||
func br_switchPlayAndPause(viewModel: BRPlayerViewModel) {
|
||||
if self.viewModel.isPlaying {
|
||||
self.pause()
|
||||
} else {
|
||||
self.play()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -332,3 +348,19 @@ extension BRPlayerListViewController {
|
||||
return BRPlayerCache.prefetch(urlString: url)
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: -------------- 系统回调 --------------
|
||||
extension BRPlayerListViewController {
|
||||
|
||||
@objc func didBecomeActiveNotification() {
|
||||
if self.viewModel.isPlaying && isDidAppear {
|
||||
self.viewModel.currentPlayer?.start()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func willResignActiveNotification() {
|
||||
self.viewModel.currentPlayer?.pause()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import UIKit
|
||||
|
||||
@objc protocol BRPlayerControlProtocol {
|
||||
|
||||
|
||||
var isCurrent: Bool { get set }
|
||||
///点击事件
|
||||
func singleTapEvent()
|
||||
|
||||
|
@ -11,6 +11,7 @@ import UIKit
|
||||
|
||||
|
||||
var videoInfo: BRVideoInfoModel? { get set }
|
||||
var shortModel: BRShortModel? { get set }
|
||||
|
||||
var isCurrent: Bool { get set }
|
||||
|
||||
|
@ -16,7 +16,7 @@ class BRPlayerControlView: UIView, BRPlayerControlProtocol {
|
||||
|
||||
weak var viewModel: BRPlayerViewModel? {
|
||||
didSet {
|
||||
|
||||
self.viewModel?.addObserver(self, forKeyPath: "isPlaying", context: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,18 +32,73 @@ class BRPlayerControlView: UIView, BRPlayerControlProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var playIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "play_icon_05"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
self.viewModel?.removeObserver(self, forKeyPath: "isPlaying")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
br_setupUI()
|
||||
self.updatePlayIconState()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//MARK: BRPlayerControlProtocol
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "isPlaying" {
|
||||
self.updatePlayIconState()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//MARK: BRPlayerControlProtocol
|
||||
|
||||
var isCurrent: Bool = false {
|
||||
didSet {
|
||||
self.updatePlayIconState()
|
||||
}
|
||||
}
|
||||
|
||||
func singleTapEvent() {
|
||||
self.viewModel?.switchPlayAndPause()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension BRPlayerControlView {
|
||||
|
||||
private func br_setupUI() {
|
||||
addSubview(self.playIconImageView)
|
||||
|
||||
self.playIconImageView.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension BRPlayerControlView {
|
||||
|
||||
private func updatePlayIconState() {
|
||||
if isCurrent == true, self.viewModel?.isPlaying != true {
|
||||
self.playIconImageView.isHidden = false
|
||||
} else {
|
||||
self.playIconImageView.isHidden = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,11 @@ class BRPlayerListCell: BRCollectionViewCell, BRPlayerProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
var isCurrent: Bool = false
|
||||
var isCurrent: Bool = false {
|
||||
didSet {
|
||||
self.controlView.isCurrent = isCurrent
|
||||
}
|
||||
}
|
||||
|
||||
var duration: Int = 0
|
||||
|
||||
@ -68,7 +72,7 @@ class BRPlayerListCell: BRCollectionViewCell, BRPlayerProtocol {
|
||||
}
|
||||
|
||||
private lazy var player: BRPlayer = {
|
||||
let player = BRPlayer(controlView: nil)
|
||||
let player = BRPlayer(controlView: self.controlView)
|
||||
player.playerView = self.playerView
|
||||
player.delegate = self
|
||||
|
||||
|
@ -11,6 +11,8 @@ import UIKit
|
||||
@objc protocol BRPlayerViewModelDelegate {
|
||||
|
||||
@objc optional func br_currentVideoPlayFinish(viewModel: BRPlayerViewModel)
|
||||
|
||||
@objc optional func br_switchPlayAndPause(viewModel: BRPlayerViewModel)
|
||||
}
|
||||
|
||||
|
||||
@ -42,4 +44,10 @@ extension BRPlayerViewModel {
|
||||
self.delegate?.br_currentVideoPlayFinish?(viewModel: self)
|
||||
}
|
||||
|
||||
///切换播放跟暂停
|
||||
func switchPlayAndPause() {
|
||||
self.delegate?.br_switchPlayAndPause?(viewModel: self)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
22
BeeReel/Sources/Assets.xcassets/icon/episode_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/episode_icon_01.imageset/Frame@2x.png
vendored
Normal file
After Width: | Height: | Size: 622 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/episode_icon_01.imageset/Frame@3x.png
vendored
Normal file
After Width: | Height: | Size: 870 B |
22
BeeReel/Sources/Assets.xcassets/icon/explore_title_icon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Discover@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Discover@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/explore_title_icon.imageset/Discover@2x.png
vendored
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/explore_title_icon.imageset/Discover@3x.png
vendored
Normal file
After Width: | Height: | Size: 5.3 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_02.imageset/Frame@2x.png
vendored
Normal file
After Width: | Height: | Size: 479 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_02.imageset/Frame@3x.png
vendored
Normal file
After Width: | Height: | Size: 736 B |
22
BeeReel/Sources/Assets.xcassets/icon/play_icon_05.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Polygon 1@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Polygon 1@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/play_icon_05.imageset/Polygon 1@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/play_icon_05.imageset/Polygon 1@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/search_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/search_icon_01.imageset/Frame@2x.png
vendored
Normal file
After Width: | Height: | Size: 783 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/search_icon_01.imageset/Frame@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.1 KiB |