1
@ -62,4 +62,8 @@ extension UIColor {
|
|||||||
static func color5A5D45(alpha: CGFloat = 1) -> UIColor {
|
static func color5A5D45(alpha: CGFloat = 1) -> UIColor {
|
||||||
return UIColor(rgb: 0x5A5D45, alpha: alpha)
|
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)
|
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() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.edgesForExtendedLayout = .all
|
self.edgesForExtendedLayout = .all
|
||||||
@ -67,12 +101,44 @@ extension BRExploreViewController {
|
|||||||
self.collectionView.layer.cornerRadius = 20
|
self.collectionView.layer.cornerRadius = 20
|
||||||
self.collectionView.layer.masksToBounds = true
|
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
|
self.collectionView.snp.remakeConstraints { make in
|
||||||
make.left.equalToSuperview().offset(15)
|
make.left.equalToSuperview().offset(15)
|
||||||
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 50)
|
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 50)
|
||||||
make.width.equalTo(contentSize.width)
|
make.width.equalTo(contentSize.width)
|
||||||
make.height.equalTo(contentSize.height)
|
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 {
|
func br_playerListViewController(_ viewController: BRPlayerListViewController, _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||||
return dataArr.count
|
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() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.statusBarStyle = .lightContent
|
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()
|
br_setupUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +135,11 @@ class BRPlayerListViewController: BRViewController {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pause() {
|
||||||
|
self.viewModel.currentPlayer?.pause()
|
||||||
|
self.viewModel.isPlaying = false
|
||||||
|
}
|
||||||
|
|
||||||
func reloadData(completion: (() -> Void)? = nil) {
|
func reloadData(completion: (() -> Void)? = nil) {
|
||||||
|
|
||||||
UIView.performWithoutAnimation {
|
UIView.performWithoutAnimation {
|
||||||
@ -276,6 +285,13 @@ extension BRPlayerListViewController: BRPlayerViewModelDelegate {
|
|||||||
scrollToNextEpisode()
|
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)
|
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 {
|
@objc protocol BRPlayerControlProtocol {
|
||||||
|
|
||||||
|
|
||||||
|
var isCurrent: Bool { get set }
|
||||||
///点击事件
|
///点击事件
|
||||||
func singleTapEvent()
|
func singleTapEvent()
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import UIKit
|
|||||||
|
|
||||||
|
|
||||||
var videoInfo: BRVideoInfoModel? { get set }
|
var videoInfo: BRVideoInfoModel? { get set }
|
||||||
|
var shortModel: BRShortModel? { get set }
|
||||||
|
|
||||||
var isCurrent: Bool { get set }
|
var isCurrent: Bool { get set }
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class BRPlayerControlView: UIView, BRPlayerControlProtocol {
|
|||||||
|
|
||||||
weak var viewModel: BRPlayerViewModel? {
|
weak var viewModel: BRPlayerViewModel? {
|
||||||
didSet {
|
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) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
br_setupUI()
|
||||||
|
self.updatePlayIconState()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
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() {
|
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
|
var duration: Int = 0
|
||||||
|
|
||||||
@ -68,7 +72,7 @@ class BRPlayerListCell: BRCollectionViewCell, BRPlayerProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lazy var player: BRPlayer = {
|
private lazy var player: BRPlayer = {
|
||||||
let player = BRPlayer(controlView: nil)
|
let player = BRPlayer(controlView: self.controlView)
|
||||||
player.playerView = self.playerView
|
player.playerView = self.playerView
|
||||||
player.delegate = self
|
player.delegate = self
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ import UIKit
|
|||||||
@objc protocol BRPlayerViewModelDelegate {
|
@objc protocol BRPlayerViewModelDelegate {
|
||||||
|
|
||||||
@objc optional func br_currentVideoPlayFinish(viewModel: BRPlayerViewModel)
|
@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)
|
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 |