Adding a segmentedcontrol to a navigationbar in a view controller - ios

I have a UIViewController with a navigation bar on top. I want to replace the title with a segmented control.
class AViewController: UIViewController
{
private var navigationbar = UINavigationBar();
private var segment = UISegmentedControl();
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
buildThebar();
}
func buildThebar()
{
navigationbar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 64));
navigationbar.backgroundColor = UIColor(red: 200/255, green: 200/255, blue: 200/255, alpha: 1.0);
segment = UISegmentedControl(items: ["Testy", "Tests"]);
segment.sizeToFit();
segment.tintColor = UIColor(red: 104/255, green: 90/255, blue: 132/255, alpha: 1.0);
let cancel = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelbar(sender:)));
cancel.tintColor = UIColor(red: 104/255, green: 90/255, blue: 132/255, alpha: 1.0);
let title = UINavigationItem(title: "Testing");
title.leftBarButtonItem = cancel;
navigationbar.setItems([title], animated: false);
self.navigationItem.titleView = segment;
// self.navigationItem.leftBarButtonItem = cancel;
self.view.addSubview(navigationbar);
}

Ok found issue.
What you missed is setting titleView to the navigation item you created.
title.titleView = segment
You are adding titleView to navigation item self.navigationItem.titleView = segment; but you need to set it to your navigationItem which you are passing to your navigation bar.
Final code
func buildThebar()
{
navigationbar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 64));
navigationbar.backgroundColor = UIColor(red: 200/255, green: 200/255, blue: 200/255, alpha: 1.0);
segment = UISegmentedControl(items: ["Testy", "Tests"]);
segment.sizeToFit();
segment.tintColor = UIColor(red: 104/255, green: 90/255, blue: 132/255, alpha: 1.0);
let cancel = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: nil);
cancel.tintColor = UIColor(red: 104/255, green: 90/255, blue: 132/255, alpha: 1.0);
let title = UINavigationItem(title: "Testing"); //better let title = UINavigationItem()
title.leftBarButtonItem = cancel;
title.titleView = segment
navigationbar.setItems([title], animated: false);
// self.navigationItem.leftBarButtonItem = cancel;
self.view.addSubview(navigationbar);
}
EDIT:
There is another issue with how you are setting navigation bar frame. O/P with your code looks like
I believe thats not what you want! the reason why it looks like that is because your frame starts from y = 0 but in iPhone and iPads portait mode there is a status bar on top which consumes variable amount of space based on various condition (Usually people hardcode or assume it to be 20 but iPhone X the height status bar might vary and even in normal iPhones when you receive a call status bar height changes). Its always better to use auto layout and safe margin to add navigation bar to View.
But if you really wanna hard code frames then you can use
navigationbar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: self.view.bounds.width, height: 44));
O/P looks like
Hope it helps.

let title = UINavigationItem()
title.titleView = segment
title.rightBarButtonItem = cancel
navigationbar.setItems([title], animated: false);
self.view.addSubview(navigationbar);
Just a matter of order of assignment of the objects in operation.

Related

Change Tab Bar background transparency

I am trying to make my Tab Bar in my tab bar controller to have a low opacity background, so it is semi transparent, i am trying to do this programatically, however the background changes to the correct color, but always appears solid, with no transparency.
Here is the code in my TabBarViewController
class TabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.unselectedItemTintColor = UIColor(red: 17.0/255.0, green: 70.0/255.0, blue: 95.0/255.0, alpha: 0.4)
self.tabBar.barTintColor = UIColor(red: 17.0/255.0, green: 70.0/255.0, blue: 95.0/255.0, alpha: 0.5)
// Do any additional setup after loading the view.
}
}
For such a case, you should generate a customized UIImage to the tab bar backgroundimage property.
Let's assume that your desired color for your tab bar -that should be transparent- is black, you could implement in your custom UITabBarController:
class TabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let transperentBlackColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 0.5)
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
transperentBlackColor.setFill()
UIRectFill(rect)
if let image = UIGraphicsGetImageFromCurrentImageContext() {
tabBar.backgroundImage = image
}
UIGraphicsEndImageContext()
}
}
So, as an Output, if we assumed that the background color of your view controller is blue, it should looks like:
As shown, the tab bar is not purely black, it contains transparency (0.5) as expected.
Also, for checking how you could generate a solid-color UIImage, you could check this SO answer : Create UIImage with solid color in Swift.
Just replace barTintColor with backgroundColor.
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.unselectedItemTintColor = UIColor(red: 17.0/255.0, green: 70.0/255.0, blue: 95.0/255.0, alpha: 0.4)
self.tabBar.backgroundColor = UIColor(red: 17.0/255.0, green: 70.0/255.0, blue: 95.0/255.0, alpha: 0.5)
// Do any additional setup after loading the view.
}
private func setTabbarOpacity() {
let transperentBlackColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 0.75)
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
transperentBlackColor.setFill()
UIRectFill(rect)
if let image = UIGraphicsGetImageFromCurrentImageContext() {
tabBar.backgroundImage = image
}
UIGraphicsEndImageContext()
}

Using PageMenu with Storyboards Swift 3

I'm trying to use this repo to create a PageMenu like you'd find on Instagram. I have the slide functionality working but the scroll menu does not appear underneath the navbar like it should. I've looked at Implementing PageMenu / initializing view controllers from storyboard but it doesn't really help my issue. I have also tried using the demo provided in the repo and customising it to my needs but then when I drag it on to my project it leaves out the scroll menu.
Here is my code in the viewControler:
// Initialize view controllers to display and place in array
var controllerArray : [UIViewController] = []
let controller1 : TestTableViewController = TestTableViewController(nibName: "TestTableViewController", bundle: nil)
controller1.parentNavigationController = self.navigationController
controller1.title = "FAVOURITES"
controllerArray.append(controller1)
let controller2 : RecentsTableViewController = RecentsTableViewController(nibName: "RecentsTableViewController", bundle: nil)
controller2.title = "RECIPES"
controller2.parentNavigationController = self.navigationController
controllerArray.append(controller2)
// Customize menu (Optional)
let parameters: [CAPSPageMenuOption] = [
.menuItemSeparatorWidth(4.3),
.scrollMenuBackgroundColor(UIColor.white),
.viewBackgroundColor(UIColor(red: 247.0/255.0, green: 247.0/255.0, blue: 247.0/255.0, alpha: 1.0)),
.bottomMenuHairlineColor(UIColor(red: 33/255.0, green: 161/255.0, blue: 77/255.0, alpha: 1)),
.selectionIndicatorColor(UIColor(red: 33/255.0, green: 161/255.0, blue: 77/255.0, alpha: 1.0)),
.menuMargin(20.0),
.menuHeight(40.0),
.selectedMenuItemLabelColor(UIColor(red: 33/255.0, green: 161/255.0, blue: 77/255.0, alpha: 1.0)),
.unselectedMenuItemLabelColor(UIColor(red: 40.0/255.0, green: 40.0/255.0, blue: 40.0/255.0, alpha: 1.0)),
.menuItemFont(UIFont(name: "HelveticaNeue-Medium", size: 14.0)!),
.useMenuLikeSegmentedControl(true),
.menuItemSeparatorRoundEdges(true),
.selectionIndicatorHeight(2.0),
.menuItemSeparatorPercentageHeight(0.1)
]
// Initialize scroll menu
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height), pageMenuOptions: parameters)
// Optional delegate
pageMenu!.delegate = self
self.view.addSubview(pageMenu!.view)
}
Please help me if you can. Thanks in advance! :)
Replace this
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height), pageMenuOptions: parameters)
With
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 64, width: self.view.frame.width, height: self.view.frame.height), pageMenuOptions: parameters)
You have to give y to 64 because status bar and navigation bar covers 64 points.

Shadow discoloring the navigation bar

The shadow is appearing on top of the navigation bar. Is there anyway to move the shadow underneath the bar or add some code so it doesn't discolor the bar?
This is the code I use in my navigation controller:
import UIKit
class navigationController:UINavigationController, UIViewControllerTransitioningDelegate{
override func viewDidLoad()
{
var appblue = UIColor(red: 109/255, green: 208/255, blue:247/255, alpha: 1.0)
self.navigationBar.barTintColor = appblue
self.navigationBar.layer.masksToBounds = false
self.navigationBar.layer.shadowColor = UIColor.black.cgColor
self.navigationBar.layer.shadowOpacity = 0.7
self.navigationBar.layer.shadowOffset = CGSize(width: 0, height: 2.0)
self.navigationBar.layer.shadowRadius = 4
}
}
and this is what it looks like:
When it should be this color:
Any suggestions?
This is what im trying to make it look like(photo shopped picture):
(the top bar bottom shadow while retaining the second bars color)
Added a image view with a gradient to the bottom of the bar to accomplish what I was going for, Thanks to #Anbu.Karthik for linking another question that I was able to adapt. This is my current code:
import UIKit
class navigationController:UINavigationController, UIViewControllerTransitioningDelegate{
override func viewDidLoad()
{
var appblue = UIColor(red: 109/255, green: 208/255, blue:247/255, alpha: 1.0)
self.navigationBar.barTintColor = appblue
self.navigationBar.layer.masksToBounds = false
var yPosition = self.navigationBar.layer.frame.height
var rectWidth = self.navigationBar.layer.frame.width
let gradient = CAGradientLayer()
let bottomShadow: UIImageView = UIImageView()
bottomShadow.frame = CGRect(x: 0, y: yPosition, width: rectWidth, height: 8)
gradient.frame = bottomShadow.bounds
gradient.colors = [UIColor.lightGray.cgColor, UIColor(white: 1, alpha: 0).cgColor]
navigationBar.addSubview(bottomShadow)
bottomShadow.layer.insertSublayer(gradient, at: 0)
}
}

Setting gradient both on Navigation Bar and Status bar

I'm trying to change the background of a navigation bar by creating a layer and adding it as a sublayer to the navigation bar. However, this is only affecting the navigation bar.
I wan't it to affect the whole top of the screen. Code included:
let navBarLayer = StyleUtils.createGradientLayerWithColors(color: StyleUtils.Colors.SKY_BLUE, frame: (self.navigationController?.navigationBar.bounds)!)
self.navigationController?.navigationBar.layer.addSublayer(navBarLayer)
The createGradientLayerWithColors function returns a CAGradientLayer for the given frame.
What am I missing? Thank you in advance.
EDIT:
I tried Nathaniel answer, but got this:
It's worth mentioning that this is also a TableView.
SOLUTION:
I found this question that helped me solve the problem.
The final correct code is:
func setNavBarColor() {
let navBar = self.navigationController?.navigationBar
//Make navigation bar transparent
navBar?.setBackgroundImage(UIImage(), for: .default)
navBar?.shadowImage = UIImage()
navBar?.isTranslucent = true
//Create View behind navigation bar and add gradient
let behindView = UIView(frame: CGRect(x: 0, y:0, width: UIApplication.shared.statusBarFrame.width, height: UIApplication.shared.statusBarFrame.height + (navBar?.frame.height)!))
let layerTop = StyleUtils.createGradientLayerWithColors(color: StyleUtils.Colors.SKY_BLUE, frame: behindView.bounds)
behindView.layer.insertSublayer(layerTop, at: 0)
self.navigationController?.view.insertSubview(behindView, belowSubview: navBar!)
}
This is how I manage it.
First I set the NavigationBar to transparent:
self.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.isTranslucent = true
self.navigationBar.backgroundColor = UIColor.clear
Then I add the gradient to the view behind the status bar and the navigation bar:
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: UIApplication.sharedApplication().statusBarFrame.width, height: UIApplication.sharedApplication().statusBarFrame.height + self.navigationController!.navigationBar.frame.height)
gradient.locations = [0.0,1.0]
gradient.colors = [UIColor.anyColor().colorWithAlphaComponent(0.4).CGColor, UIColor.clearColor().CGColor]
self.view.layer.addSublayer(gradient)
self.view.backgroundColor = UIColor.clear
My option:
let gradientLayer = CAGradientLayer()
let layerY = -UIApplication.shared.statusBarFrame.size.height as CGFloat
let layerHeight = (self.navigationController?.navigationBar.frame.size.height)! + UIApplication.shared.statusBarFrame.size.height as CGFloat
gradientLayer.frame = CGRect(x: 0, y: layerY, width: 1366, height: layerHeight)
gradientLayer.colors = [UIColor(red: 16/255.0, green: 57/255.0, blue: 82/255.0, alpha: 1.0).cgColor, UIColor(red: 17/255.0, green: 132/255.0, blue: 157/255.0, alpha: 1.0).cgColor]
self.navigationController?.navigationBar.layer.addSublayer(gradientLayer)
It is not better, simply just another way to do the same.

Change tintColor of custom navigation bar image

I have a navigation bar with an UIImage. I want to change the colour of it, but when I use my code, the default black colour is used. My code is below.
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 26, height: 26))
imageView.contentMode = .ScaleAspectFit
let image = UIImage(named: "pinpoint.png")
imageView.image = image
navigationItem.titleView = imageView
imageView.image = UIImage(named: "pinpoint.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
imageView.tintColor = UIColor(red: 22.0/255.0, green: 40.0/255.0, blue: 86.0/255.0, alpha: 1.0)
}
The colour I want to use is on the last line of the snippet.
You can try this way:
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named:"pinpoint.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate))
imageView.contentMode = .ScaleAspectFit
navigationItem.titleView = imageView
imageView.tintColor = UIColor(red: 22.0/255.0, green: 40.0/255.0, blue: 86.0/255.0, alpha: 1.0)
}
Hope this help. :)

Resources