setup for mini player to episode detail transformation
MODIFY
Podcast.xcodeproj/project.pbxproj
Podcast.xcodeproj/project.pbxproj
/* Begin PBXBuildFile section */
421501271D9F5FE1002839D1 /* Player.swift in Sources */ = {isa = PBXBuildFile; fileRef = 421501261D9F5FE1002839D1 /* Player.swift */; };
- 424EAA391E5DDF9900F0126C /* TempPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 424EAA381E5DDF9900F0126C /* TempPlayerViewController.swift */; };
+ 4253114D1E5E4CC500DF06F6 /* MiniPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4253114C1E5E4CC500DF06F6 /* MiniPlayerView.swift */; };
425B393D1E512F5D00283CA4 /* PlayerControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425B393C1E512F5D00283CA4 /* PlayerControlsView.swift */; };
425C90621E5A5827004BB7AD /* EpisodeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425C90611E5A5827004BB7AD /* EpisodeDetailView.swift */; };
4290028A1E5CA6A20069F0BF /* PlayerHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 429002891E5CA6A20069F0BF /* PlayerHeaderView.swift */; };
/* Begin PBXFileReference section */
13C8D9A7A7FB0C3D27C81500 /* Pods-PodcastTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PodcastTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PodcastTests/Pods-PodcastTests.debug.xcconfig"; sourceTree = "<group>"; };
421501261D9F5FE1002839D1 /* Player.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Player.swift; sourceTree = "<group>"; };
- 424EAA381E5DDF9900F0126C /* TempPlayerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TempPlayerViewController.swift; path = ../TempPlayerViewController.swift; sourceTree = "<group>"; };
+ 4253114C1E5E4CC500DF06F6 /* MiniPlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiniPlayerView.swift; sourceTree = "<group>"; };
425B393C1E512F5D00283CA4 /* PlayerControlsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerControlsView.swift; sourceTree = "<group>"; };
425C90611E5A5827004BB7AD /* EpisodeDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EpisodeDetailView.swift; sourceTree = "<group>"; };
429002891E5CA6A20069F0BF /* PlayerHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerHeaderView.swift; sourceTree = "<group>"; };
425B393C1E512F5D00283CA4 /* PlayerControlsView.swift */,
425C90611E5A5827004BB7AD /* EpisodeDetailView.swift */,
429002891E5CA6A20069F0BF /* PlayerHeaderView.swift */,
+ 4253114C1E5E4CC500DF06F6 /* MiniPlayerView.swift */,
);
name = Player;
sourceTree = "<group>";
7F97FBDD1D8663000073FC0F /* REST.swift */,
42F684EA1D80CC7E0035217A /* PlayerViewController.swift */,
421501261D9F5FE1002839D1 /* Player.swift */,
- 424EAA381E5DDF9900F0126C /* TempPlayerViewController.swift */,
FDF1D1CE1DAEE2E300697379 /* ProfileViewController.swift */,
42D7D9901D80C557000691A4 /* Main.storyboard */,
42D7D9931D80C557000691A4 /* Assets.xcassets */,
D3E2692B1E5E7CBF00793569 /* RecommendedCard.swift in Sources */,
D34A2EE51E6364830047AF32 /* Tag.swift in Sources */,
D300C0921DAEF801000CDBF5 /* CategoriesFeedViewController.swift in Sources */,
+ 4253114D1E5E4CC500DF06F6 /* MiniPlayerView.swift in Sources */,
D3DB5A651DA18FC600E550E8 /* CategoriesCollectionViewCell.swift in Sources */,
FD20F5721E52067400721C46 /* SeriesDetailViewController.swift in Sources */,
4290028A1E5CA6A20069F0BF /* PlayerHeaderView.swift in Sources */,
447DA8691E5C998E0002BCA0 /* DiscoverTableViewHeaderView.swift in Sources */,
D3E2692F1E5E806A00793569 /* TagCard.swift in Sources */,
956D85131E51926800D95F7A /* EndpointRequest.swift in Sources */,
- 424EAA391E5DDF9900F0126C /* TempPlayerViewController.swift in Sources */,
42D7D98D1D80C557000691A4 /* AppDelegate.swift in Sources */,
D39BEE1D1D8A073200131936 /* Series.swift in Sources */,
42F684EB1D80CC7E0035217A /* PlayerViewController.swift in Sources */,

MODIFY
Podcast/AppDelegate.swift
Podcast/AppDelegate.swift
@@ -21,6 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var profileViewController: ProfileViewController!
var bookmarkViewController: BookmarkViewController!
var feedViewControllerNavigationController: UINavigationController!
+ var playerViewController: PlayerViewController!
var discoverViewControllerNavigationController: UINavigationController!
var profileViewControllerNavigationController: UINavigationController!
var bookmarkViewControllerNavigationController: UINavigationController!
@@ -31,6 +32,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
feedViewController = FeedViewController()
profileViewController = ProfileViewController()
bookmarkViewController = BookmarkViewController()
+ playerViewController = PlayerViewController()
discoverViewControllerNavigationController = UINavigationController(rootViewController: discoverViewController)
feedViewControllerNavigationController = UINavigationController(rootViewController: feedViewController)
@@ -46,7 +48,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Tab bar controller
tabBarController = TabBarController()
tabBarController.transparentTabBarEnabled = true
- tabBarController.numberOfTabs = 4
+ tabBarController.numberOfTabs = 5
tabBarController.setUnselectedImage(image: UIImage(named: "home_unselected_icon")!, forTabAtIndex: 0)
tabBarController.setUnselectedImage(image: UIImage(named: "magnifying_glass_unselected_icon")!, forTabAtIndex: 1)
tabBarController.setUnselectedImage(image: UIImage(named: "bookmark_unselected_icon")!, forTabAtIndex: 2)
@@ -72,6 +74,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
self.tabBarController.present(self.profileViewControllerNavigationController, animated: false, completion: nil)
}, forTabAtIndex: 3)
+ tabBarController.addBlockToExecuteOnTabBarButtonPress(block: {
+ self.tabBarController.present(self.playerViewController, animated: false, completion: nil)
+ }, forTabAtIndex: 4)
+
// Main window setup
window = UIWindow()

ADD
Podcast/Assets.xcassets/down_arrow.imageset/Contents.json
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "Line.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "Line@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "Line@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file

ADD
Podcast/Assets.xcassets/down_arrow.imageset/Line.png
Podcast/Assets.xcassets/down_arrow.imageset/Line.png
Binary files /dev/null and b/Podcast/Assets.xcassets/down_arrow.imageset/Line.png differ

ADD
Podcast/Assets.xcassets/down_arrow.imageset/Line@2x.png
Podcast/Assets.xcassets/down_arrow.imageset/Line@2x.png
Binary files /dev/null and b/Podcast/Assets.xcassets/down_arrow.imageset/Line@2x.png differ

ADD
Podcast/Assets.xcassets/down_arrow.imageset/Line@3x.png
Podcast/Assets.xcassets/down_arrow.imageset/Line@3x.png
Binary files /dev/null and b/Podcast/Assets.xcassets/down_arrow.imageset/Line@3x.png differ

ADD
Podcast/Assets.xcassets/mini_play_icon.imageset/Contents.json
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "PlayButton.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "PlayButton@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "PlayButton@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file

ADD
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton.png
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton.png
Binary files /dev/null and b/Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton.png differ

ADD
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@2x.png
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@2x.png
Binary files /dev/null and b/Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@2x.png differ

ADD
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@3x.png
Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@3x.png
Binary files /dev/null and b/Podcast/Assets.xcassets/mini_play_icon.imageset/PlayButton@3x.png differ

MODIFY
Podcast/PlayerControlsView.swift
Podcast/PlayerControlsView.swift
@@ -36,7 +36,7 @@ class PlayerControlsView: UIView {
backgroundColor = .white
slider = UISlider(frame: .zero)
- slider.frame = CGRect(x: 0, y: 0, width: frame.width - (2 * SliderInset), height: SliderHeight)
+ slider.frame.size = CGSize(width: frame.width - (2 * SliderInset), height: SliderHeight)
slider.center = CGPoint(x: frame.width/2, y: SliderCenterY)
addSubview(slider)

MODIFY
Podcast/PlayerViewController.swift
Podcast/PlayerViewController.swift
@@ -14,31 +14,33 @@ class PlayerViewController: UIViewController, PlayerDelegate {
var controlsView: PlayerControlsView!
var episodeDetailView: EpisodeDetailView!
var playerHeaderView: PlayerHeaderView!
- var episodeNameLabel: UILabel!
- var seriesNameLabel: UILabel!
-
- let EpisodeDetailViewYVal: CGFloat = 87
+ var miniPlayerView: MiniPlayerView!
+ var isMini: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
- view.backgroundColor = .podcastGrayLight
+ view.backgroundColor = .white
playerHeaderView = PlayerHeaderView(frame: .zero)
playerHeaderView.frame.size.width = view.frame.width
- playerHeaderView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(playerHeaderTapped)))
+ playerHeaderView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(changeMode)))
+ playerHeaderView.alpha = 0.0
view.addSubview(playerHeaderView)
+ miniPlayerView = MiniPlayerView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 0))
+ miniPlayerView.frame.size.width = view.frame.width
+ miniPlayerView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(changeMode)))
+ view.addSubview(miniPlayerView)
+
episodeDetailView = EpisodeDetailView(frame: .zero)
episodeDetailView.frame.size.width = view.frame.width
- episodeDetailView.frame.origin.y = EpisodeDetailViewYVal
+ episodeDetailView.frame.origin.y = playerHeaderView.frame.maxY
view.addSubview(episodeDetailView)
controlsView = PlayerControlsView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 0))
controlsView.frame.origin.y = view.frame.height - controlsView.frame.size.height
view.addSubview(controlsView)
- // TODO: add comments section
-
updateUI()
Player.sharedInstance.delegate = self
@@ -48,13 +50,33 @@ class PlayerViewController: UIViewController, PlayerDelegate {
updateUI()
}
- func playerHeaderTapped() {
- dismiss(animated: true, completion: nil)
+ func changeMode() {
+ isMini ? expand() : collapse()
+ }
+
+ func expand() {
+ UIView.animate(withDuration: 1.0, animations: {
+ self.miniPlayerView.alpha = 0.0
+ self.playerHeaderView.alpha = 1.0
+ self.view.frame.origin.y = 0
+ })
+ isMini = false
+ }
+
+ func collapse() {
+ UIView.animate(withDuration: 1.0, animations: {
+ self.miniPlayerView.alpha = 1.0
+ self.playerHeaderView.alpha = 0.0
+ // TODO: is there a way to get the TabBar's height? Replace 110 with this value
+ self.view.frame.origin.y = self.view.frame.height - 110
+ })
+ isMini = true
}
func updateUI() {
playerHeaderView.updateUI()
episodeDetailView.updateUI()
controlsView.updateUI()
+ miniPlayerView.updateUI()
}
}

setup for mini player to episode detail transformation