Addding UIView between tabBar and Navigation view in UITabBarController - swift

I am working on a project that uses a UITabBarController for displaying all the different UIViewControllers but now I need to add a mini player just in between the tabBar and the navigation view (ViewControllers will have to resize too).
Is there anyway I can achieve that by reusing the existing class?
EDIT
I have tried 2 methods:
1- Adding it into the view. Gets Added but above of the VCs
let aView = UIView()
view.addSubview(aView)
aView.backgroundColor = .white
aView.anchor(top: nil, leading: view.leadingAnchor, bottom: tabBar.topAnchor, trailing: view.trailingAnchor, size: .init(width: 0, height: 100))
2- Adding it into the tabBar. It might sound silly but I thought It would work.
let viewOverTabBar = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
viewOverTabBar.backgroundColor = UIColor.black
tabBar.addSubview(viewOverTabBar)

Add your view as subview to view of UITabBarViewController not tab bar itself. Just place it above tab bar.
Also change:
aView.anchor(top: nil, leading: view.leadingAnchor, bottom: tabBar.topAnchor, trailing: view.trailingAnchor, size: .init(width: 0, height: 100))
to setting directly frame property of your view.
Also you need to do in in viewWillAppear method.

You can try this way :
class MyTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.createSmallPlayer()
}
func createSmallPlayer() {
let viewOverTabBar = UIView(frame: CGRect(x: 0, y: self.tabBar.frame.origin.y-40, width: self.tabBar.frame.size.width, height: 30))
viewOverTabBar.backgroundColor = UIColor.brown
//viewOverTabBar.layer.cornerRadius = viewOverTabBar.frame.size.height/2
viewOverTabBar.layer.masksToBounds = false
viewOverTabBar.layer.shadowColor = UIColor.black.withAlphaComponent(0.5).cgColor
viewOverTabBar.layer.shadowRadius = 5.0
viewOverTabBar.layer.shadowOffset = CGSize(width: 0.0, height: -5.0)
viewOverTabBar.layer.shadowOpacity = 0.5
//tabBar.addSubview(viewOverTabBar)
view.addSubview(viewOverTabBar)
}
}
And make sure that your all other view controller(which will navigate within tabbar) adjust frame accordingly.
Either you have to manage bottom view of all view controller by 30 pixels up and keep 30 pixels space blank at bottom, so no any content hide behind your player view.
Or you have you add :
Container view UIView same as added player view.
In that you have to add view controller's view with navigation controller as subview(Refer this : Adding a view controller as a subview in another view controller).

Related

View buttons are not anymore clickable after adding a .xib view as subview

I have a viewcontroller where a card from below is displayed. I used a .xib view to swipe from the bottom of view controller bu the viewcontroller buttons are not anymore clickable after adding .xib view as subview in the viewcontroller's view even when the .xib view is collapsed. "cardViewController" is the name of .xib view.
var cardViewController:FrenchiasCardViewController!
func setupCard()
{
// Setup starting and ending card height
endCardHeight = self.view.frame.height * 0.9
startCardHeight = self.view.frame.height * 0.08
// Add Visual Effects View
visualEffectView = UIVisualEffectView()
visualEffectView.frame = self.view.frame
self.view.addSubview(visualEffectView)
// Add CardViewController xib to the bottom of the screen, clipping bounds so that the corners can be rounded
cardViewController = FrenchiasCardViewController(nibName:"FrenchiasCardViewController", bundle:nil)
self.view.addSubview(cardViewController.view)
cardViewController.view.frame = CGRect(x: 0, y: self.view.frame.height - startCardHeight, width: self.view.bounds.width, height: endCardHeight)
cardViewController.view.clipsToBounds = true
// Add tap and pan recognizers
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(NewAddressView.handleCardTap(recognzier:)))
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(NewAddressView.handleCardPan(recognizer:)))
cardViewController.handleArea.addGestureRecognizer(tapGestureRecognizer)
cardViewController.handleArea.addGestureRecognizer(panGestureRecognizer)
}
let frameAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 1) {
switch state {
case .expanded:
// If expanding set popover y to the ending height and blur background
self.cardViewController.view.frame.origin.y = self.view.frame.height - self.endCardHeight
self.visualEffectView.effect = UIBlurEffect(style: .dark)
case .collapsed:
// If collapsed set popover y to the starting height and remove background blur
self.cardViewController.view.frame.origin.y = self.view.frame.height - self.startCardHeight
self.visualEffectView.effect = nil
}
}

Add View to TableViewController with NavigationController

For adding a view to a UITableViewController I added the view to navigationController as below:
self.navigationController?.view.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.rightAnchor.constraint(equalTo: (self.navigationController?.view.rightAnchor)!).isActive = true
view.bottomAnchor.constraint(equalTo: (self.navigationController?.view.bottomAnchor)!).isActive = true
view.widthAnchor.constraint(equalToConstant: 70).isActive = true
view.heightAnchor.constraint(equalToConstant: 120).isActive = true
But when you want to push a new ViewController it will keeps the added view (myView).
I tried to add myView to view and tableView like below:
self.view.addSubview(myView)
self.tableView.addSubview(myView)
but both doesn't work.
I know I can use UIViewController and add a UITableView and then it is easier to add myView to UIViewController.
Should I add myView to another view?
The View of a UITableViewController is a UITableView, so you cannot add subviews to the controller on top of the table.
You have to derive from UIViewController to get full layout control.
Instead of using UITableViewController, use a UIViewController and put a UITableView within it.
Yes it's possible in UITableViewConroller:
let bottomView = UIView()
bottomView.backgroundColor = .red // or your color
bottomView.frame = CGRect(x: 0, y: UIScreen.main.bounds.size.height - 78, width: tableView.frame.size.width, height: 78) // 78 or your size of view
navigationController?.view.addSubview(bottomView)
tableView.tableFooterView = UIView()
bottomView.backgroundColor = .red // or your color
bottomView.frame = CGRect(x: 0, y: UIScreen.main.bounds.size.height - 78, width: tableView.frame.size.width, height: 78) // 78 or your size of view
navigationController?.view.addSubview(bottomView)
tableView.tableFooterView = UIView()[enter image description here][1]

statusBar becomes transparent when searchBar is active

I have a UISearchController in my view controller, when the searchBar is active the status bar becomes transparent. I've tried this and this but none of them worked.
This is the view hierarchy of the view controller:
How can I make the status bar translucent?
Using this in viewDidLoad solved the problem:
var frame = UIApplication.shared.statusBarFrame
frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height*3.3)
//3.3 is a practical number
let statusBarView = UIView(frame: frame)
statusBarView.backgroundColor = sharedApplication.mainThemeColor
searchController.view.addSubview(statusBarView)

Sliding a UIView "Out of nowhere"

i am trying to create a custom dropdown menu. I will have several cards on my view which should have a dropdown menu when tapped.
Right now i am having the dropDownView having cardView.frame.maxY as its frame.origin.y value with a height of 0 and when I tap the card view I set the height of the dropDownView to its real height-value within an animation.
But that looks kind of ugly since it looks like it stretches out of nowhere. I want it to slide out of nowhere.
By that i mean it having its original size right away and sitting below the card view (cardView.frame.maxY = dropDownView.frame.maxY) When the cardView is tapped the dropDownView slides down (dropDownView.frame.origin.y = cardView.frame.maxY) within an animation.
The Problem is, that the dropDownView is bigger than the cardView. So when it sits behind the cardView it is visible above the cardView. I tried to illustrate the Problem :)
This is state A (Before View A[cardView] is tapped) (View C is just some Background View which should be visible above and below View A)
This is state B (after cardView is tapped)
Any Ideas how to solve this problem? Thank you!
In addition heres a little sample code:
class cardViewComplete: UIView {
var card: CardView!
var dropDownMenu: DropDownView!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
func initSubViews() {
self.clipsToBounds = true
card = CardView()
card.frame = self.bounds
card.addTarget(self, action: #selector(YellowTackleTicketComplete.ticketTapped), forControlEvents: .TouchDown)
dropDownMenu = DropDownView()
dropDownMenu.frame = CGRect(x: 0, y: self.bounds.maxY, width: self.bounds.width, height: 350)
dropDownMenu.hidden = true
dropDownMenu.backgroundColor = UIColor.clearColor()
self.addSubview(card)
self.insertSubview(dropDownMenu, belowSubview: card)
dropDownMenu)
}
func showDropdown() {
dropDownMenu.hidden = false
originalHeight = self.frame.size.height
print("showing")
if !animating {
animating = true
UIView.animateWithDuration(
0.7,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: [],
animations: {
self.frame.size.height = self.frame.size.height + 350
}, completion: { _ in
self.animating = false
}
)
}
self.setNeedsDisplay()
self.dropDownMenu!.setNeedsDisplay()
dropped = true
}
func ticketTapped() {
showDropdown()
}
}
What I would do is place both View A and View B inside a new view, we can call this containerView.
containerView should be big enough to hold both A and B (when B is moved down). Then set containerView to clip at bounds. So when View B is in the "up" position, it is sitting both behind View A, and clipped at the top of containerView. Therefore it is not seen at all.
Once you're ready for View B to drop to it's "down" position, just animate it going down, where it will appear to come out from the bottom of View A. Since the containerView's frame will extend far enough down to accommodate A and B (in it's down position), nothing will be clipped and both views will be visible.
card = CardView()
card.frame = self.bounds
card.addTarget(self, action: #selector(YellowTackleTicketComplete.ticketTapped), forControlEvents: .TouchDown)
dropDownMenu = DropDownView()
// I changed the frame to place it right underneath the card view
dropDownMenu.frame = CGRect(x: 0, y: card.frame.size.height - 350, width: self.bounds.width, height: 350)
dropDownMenu.hidden = true
dropDownMenu.backgroundColor = UIColor.clearColor()
let containerView = UIView()
containerView.frame = CGRect(x: 0, y: 0, width: bounds.width, height: card.frame.size.height + dropDownMenu.frame.size.height)
containerView.backgroundColor = nil
containerView.clipsAtBounds = true
containerView.addSubview(dropDownMenu)
containerView.addSubview(card)

Cocoa NSScrollView not scrolling

I try to create a scrollview. Created a scrollview via Xib, programmatically added scrolledView (a NSView that contains all subview in scrollView).
The following code shows the subviews but the scrollView not scroll. Why?
class LevelScrollController: NSViewController {
#IBOutlet var scrollView: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let scrolledView = NSView(frame: NSRect(x: 0, y: 0, width: scrollView.frame.size.width, height: 300))
// Inserisco pulsanti di esempio
for i in 1 ... 10{
scrolledView.addSubview(NSButton(frame: NSRect(x: 0, y: i*30, width: 100, height: 30)))
}
scrollView.addSubview(scrolledView)
}
Putting the code in viewDidLayout instead of viewDidLoad not change the result: not scroll
Instead of add scrolledView to subview of scrollView, set it as documentView.
Replace scrollView.addSubview(scrolledView) with scrollView.documentView = scrolledView