How to add the UISegmentedControl in UINavigationBar? - ios

I have tried to add the UISegmentedControl to the bottom of UINavigationBar with title. But i cannot add it and I cannot add UISegmentedControl in the tableView.headerView,because i need the search bar in the tableView.headerView, so there is just one solution that i need to add UISegmentedControl to the bottom of UINavigationBar. Anyone have another idea that i can solve this situation?
Here is the code that I have tried(with Swift):
class searchingViewController: UITableViewController{
override func viewDidLoad() {
var items: [AnyObject] = ["Searching Method A", "Searching Method B"]
var searchSC:UISegmentedControl!
searchSC.frame = CGRectMake(0, 0, frame.width - 20, 30)
searchSC.selectedSegmentIndex = 1
searchSC.backgroundColor = UIColor(white: 1, alpha: 1)
searchSC.layer.cornerRadius = 5.0
navigateUIToolBar = UIToolbar(frame: CGRectMake(frame.minX + 10, ios7_8Info.getStatusBarHeight()+self.navigationController!.navigationBar.frame.height+frame.minY+(21/2),
frame.width - 20, 30))
navigateUIToolBar.addSubview(searchSC)
self.navigationController?.navigationBar.addSubview(navigateUIToolBar)
}
}

To add segment control in UINavigationBar in Swift 5
let segment: UISegmentedControl = UISegmentedControl(items: ["First", "Second"])
segment.sizeToFit()
if #available(iOS 13.0, *) {
segment.selectedSegmentTintColor = UIColor.red
} else {
segment.tintColor = UIColor.red
}
segment.selectedSegmentIndex = 0
segment.setTitleTextAttributes([NSAttributedString.Key.font : UIFont(name: "ProximaNova-Light", size: 15)!], for: .normal)
self.navigationItem.titleView = segment

To put it in the navigationBar has a right left and title view for such things... accessed using....
self.navigationItem.titleView = mySegmentedControl
for future reference....
self.navigationItem.rightBarButtonItem
self.navigationItem.leftBarButtonItems // for adding an Array of items
To add it below the navigation view but have it static.. add it to the viewController.view... Are you using a UITableViewController? If so maybe switch to a UIViewController and add a tableView then your toolbarview as subviews to that self.view.

I think you are looking for this.
let searchVC = self.storyboard?.instantiateViewController(withIdentifier:"idofcontroller")
let searchController = UISearchController(searchResultsController: searchVC)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search"
navigationItem.searchController = searchController
definesPresentationContext = true
searchController.searchBar.scopeButtonTitles = ["News", "Photos", "Videos"]
searchController.searchBar.delegate = self

This is how I do it in Objective C (sorry, I haven't learned Swift yet):
- (void)viewDidLoad
{
[super viewDidLoad];
self.viewControllers = [self segmentViewControllers];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems: [self.segmentedControl addTarget: self
action: #selector(segmentClicked:)
forControlEvents: UIControlEventValueChanged];
CGFloat topOffset = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
self.toolbar = [[UIToolbar alloc] initWithFrame: CGRectMake(0, topOffset, self.navigationController.navigationBar.frame.size.width, kDefaultViewHeight)];
self.toolbar.delegate = self;
self.navigationController.navigationBar.backgroundColor = [UIColor whiteColor];
self.toolbar.backgroundColor = [UIColor whiteColor];
self.toolbar.clipsToBounds = YES;
UIBarButtonItem *segmentedControlItem = [[UIBarButtonItem alloc] initWithCustomView: self.segmentedControl];
UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace
target: nil
action: nil];
[self.toolbar setItems: #[flexibleItem, segmentedControlItem, flexibleItem] animated: YES];
[self.navigationController.view addSubview: self.toolbar];
self.segmentedControl.selectedSegmentIndex = 0;
}
And in UITableViewController (one of the segmentViewControllers):
self.tableView.contentInset = UIEdgeInsetsMake(topOffset, 0, 0, 0);
CGRect currentFrame = self.tableView.frame;
[self.tableView setFrame: CGRectMake(currentFrame.origin.x,
currentFrame.origin.y,
currentFrame.size.width,
currentFrame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height)];

You can also add the segment control to a search bar, not the navigation item. If you're like me, I needed a large title + search bar + navigation item, which would be impossible with the current top answer.
#Abhishek 's answer is close. You would do something like the following:
// Create the search controller
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.scopeButtonTitles = ["Option 1", "Option 2"]
// Make sure the scope bar is always showing, even when not actively searching
searchController.searchBar.showsScopeBar = true
// Make sure the search bar is showing, even when scrolling
navigationItem.hidesSearchBarWhenScrolling = false
// Add the search controller to the nav item
navigationItem.searchController = searchController
definesPresentationContext = true
#Gurjit Singh, the line with .showsScopeBar = true is the solution to your problem.

you can custom navigationItem's titleView, like this:
self.navigationItem.titleView = segmentview
you should not add subview to the navigationbar, for after push or pop UIViewcontroller ,the subview is still exsit on the navigationbar.

Related

How do I set up my navigation search bar in Swift to look like the Reddit App

I just started to learn how to code with Swift in Xcode, I need some help regarding the search bar. I want to add a search field bar to my navigation bar in center, and next to it i want to add two items . So far I managed to add a UISearch to my navigation bar but once I try to add items next to it, it pushes my icons above the search field.
Pressed State
Normal State
Does anyone know what to add the two menu items next to it programmatically or in the storyboard? And how to make the search field centered and a bit thinner?
My code now:
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self as? UISearchControllerDelegate
let searchBar = searchController.searchBar
searchBar.tintColor = UIColor.white
searchBar.barTintColor = UIColor.white
if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
Reddit Example
Okay, fixed it! Just used the code below. Now my next struggle is changing the background of the textfield.
//SEARCH
let searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self as? UISearchBarDelegate
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
let titleView = UIView(frame: frame)
searchController.searchBar.backgroundImage = UIImage()
searchController.searchBar.frame = frame
titleView.addSubview(searchController.searchBar)
navigationItem.titleView = titleView
}

UITableViewController overlapping the SearchBar of UISearchController in UIViewController in Swift 4

I am integrating UISearchController and UITableViewController in a ViewController.
Below is the code that I have implemented:
func configureSearchController() {
let searchTableViewController = UITableViewController()
self.searchController = UISearchController(searchResultsController: searchTableViewController)
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.searchBarStyle = .default
self.navigationItem.titleView = self.searchController.searchBar
self.searchController.searchBar.becomeFirstResponder()
self.searchController.searchBar.placeholder = "Title"
let searchBar = self.searchController.searchBar
if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.black
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 5
backgroundview.clipsToBounds = false
}
}
self.definesPresentationContext = true
// Setting delegates and other stuff
searchTableViewController.tableView.dataSource = self
searchTableViewController.tableView.delegate = self
self.searchController.delegate = self
self.searchController.dimsBackgroundDuringPresentation = true
self.searchController.searchBar.delegate = self
}
Now the problem is when I start typing in SearchBar the TableViewController is appearing over SearchBar.
How to add space between SearchBar and TableViewController?
This is how it looks :

How to add multiple buttons to navigation bar without UINavigationController?

to add a multiple button to viewController inside UINavigationController,
I just this line:
self.navigationItem.rightBarButtonItems = [my button]
but i din't succeed to add that to a view wihout UINavigationController:
//create new navigation item. and add it to the nvigation bar
customNavigationItem = UINavigationItem()
/* now we need to add the menu + search to the navigation item */
//create search button
let searchButton = UIButton();
searchButton.frame = CGRectMake(0, 0, 50.0, 50.0);
searchButton.backgroundColor = UIColor.redColor();
searchButton.titleLabel!.font = UIFont.iconmoonFont(14.0)
searchButton.titleLabel?.textColor = UIColor.whiteColor()
searchButton.titleLabel!.text = IconsConstants.SEARCH;//SEARCH ICON TEXT
searchButton.backgroundColor = UIColor.clearColor();
searchButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Center;
searchButton.contentVerticalAlignment = UIControlContentVerticalAlignment.Center;
let searchUIbarBtn = UIBarButtonItem.init(customView: searchButton)
//create menu button
let menuButton = UIButton();
menuButton.frame = CGRectMake(0, 0, 40.0, 40.0);
menuButton.titleLabel!.font = UIFont.iconmoonFont(14.0)
menuButton.backgroundColor = UIColor.whiteColor()
menuButton.titleLabel!.text = IconsConstants.MENU;//SEARCH ICON TEXT
menuButton.backgroundColor = UIColor.clearColor();
menuButton.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Center;
menuButton.contentVerticalAlignment = UIControlContentVerticalAlignment.Center;
let menuUIbarBtn = UIBarButtonItem.init(customView: menuButton)
//add button to NavigationItem
customNavigationItem.rightBarButtonItems = [menuUIbarBtn,searchUIbarBtn];
/* add navigation bar */
navigationBar = UINavigationBar();
navigationBar.frame = CGRectMake(0, statusBarHeight, self.view.frame.size.width, 44);
//navigationBar.translucent = false
navigationBar.barTintColor = UIColor.statusBarColor()
navigationBar.items = [customNavigationItem]
self.view.addSubview(navigationBar)
i can't understand why i got a bar without any button ?

Status bar changes color when searching

I'm using a UISearchController that, when clicked, makes the navigation bar rise and turn the status bar white. I want the status bar to remain green.
My UISearchController implementation:
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.placeholder = "Pesquisa por linha ou cod..."
controller.searchBar.tintColor = UIColor(netHex: 0xFFFFFF)
controller.searchBar.barTintColor = UIColor(netHex: 0x2F7C30)
controller.searchBar.clipsToBounds = true
controller.searchBar.layer.borderWidth = 1;
controller.searchBar.layer.borderColor = UIColor(netHex: 0x2F7C30).CGColor
self.navigationController!.view.backgroundColor = UIColor(netHex: 0x2F7C30)
self.tableView.tableHeaderView = controller.searchBar
return controller
})()
Before clicking on the search bar
After clicking on the search bar
Playing off of Daniel Storm's response. Adding the subview to the UISearchController's view solved the issue for me.
let statusBarView = UIView(frame: CGRectMake(0, 0,
UIApplication.sharedApplication().statusBarFrame.size.width,
UIApplication.sharedApplication().statusBarFrame.size.height))
statusBarView.backgroundColor = Colors.Primary.Regular
searchController.view.addSubview(statusBarView)
Put a UIView behind your status bar with the background color you need.
let statusBarView = UIView(frame: UIApplication.sharedApplication().statusBarFrame)
statusBarView.backgroundColor = UIColor.greenColor() // Replace with color you desire
view.addSubview(statusBarView)
By setting
scrollEdgeAppearance
buttonAppearance
backButtonAppearance
works for me fine here is the code snippet
func setNavigationBarAppreance(){
let navBar = UINavigationBar.appearance()
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithOpaqueBackground()
navigationBarAppearance.backgroundColor = .primary // replace your desired color
navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.navigationBarTintColor]
navigationBarAppearance.shadowImage = UIImage()
navigationBarAppearance.backgroundImage = UIImage()
navBar.scrollEdgeAppearance = navigationBarAppearance
navBar.compactAppearance = navigationBarAppearance
navBar.standardAppearance = navigationBarAppearance
navBar.isTranslucent = false
navBar.tintColor = .navigationBarTintColor
navBar.barTintColor = .navBarColor
}
Simply use this function in the desired Viewcontrollers or you can put it in the AppDelegate file for global appearance settings
It is enough to set backgroundImage for navigationImage
navigationController?.navigationBar.setBackgroundImage(UIImage(from: UIColor(hexString: kMainColorHex, alpha: 1)), for: .any, barMetrics: .default)
Try this:
self.navigationController?.navigationBar.isTranslucent = false
For objective C version you can use the following codes:
UIView *statusBarView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIApplication sharedApplication].statusBarFrame.size.width, [UIApplication sharedApplication].statusBarFrame.size.height)];
statusBarView.backgroundColor = [UIColor searchBarBackgroundColor];
[resultSearchController.view addSubview:statusBarView];

How to add Badges on UIBarbutton item?

Hi friends am new to iphone developing. Am struggle with add badge values on UIBarbutton item on right side. I have tried but i can't solve this problem. Can anyone help me.
Thanks in advance!
I know this post is pretty old but with iOS7, MKNumberBadgeView's appearance does not really match the tab bar item badge design.
I have found this other component which herits UIBarButtonItem and do the job very well :
https://github.com/TanguyAladenise/BBBadgeBarButtonItem
Hope this may help other iOS7 developers like me
Finally i found the way to add badges on UIBarbutton item. I searched lot but not found the correct answer. So i created UIButton and add it as a Custom view on rightbarbutton item. Add add the MKNumberBadgeView for display the badge number. Below i have add my code for you.
// Initialize NKNumberBadgeView...
MKNumberBadgeView *number = [[MKNumberBadgeView alloc] initWithFrame:CGRectMake(60, 00, 30,20)];
number.value = 10;
// Allocate UIButton
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 0, 70, 30);
btn.layer.cornerRadius = 8;
[btn setTitle:#"Button" forState:UIControlStateNormal];
[btn addTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
//[btn setBackgroundColor:[UIColor blueColor]];
[btn setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.1 alpha:0.2]];
btn.font = [UIFont systemFontOfSize:13];
//[btn setFont:[UIFont systemFontOfSize:13]];
[btn addSubview:number]; //Add NKNumberBadgeView as a subview on UIButton
// Initialize UIBarbuttonitem...
UIBarButtonItem *proe = [[UIBarButtonItem alloc] initWithCustomView:btn];
self.navigationItem.leftBarButtonItem = proe;
Thanks.
phyzalis has a good answer, there's a categorized version of his solution here:
UIBarButtonItem+Badge
Here's how you can use it:
// Build your regular UIBarButtonItem with Custom View
UIImage *image = [UIImage imageNamed:#"someImage"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0,0,image.size.width, image.size.height);
[button addTarget:self action:#selector(buttonPress:) forControlEvents:UIControlEventTouchDown];
[button setBackgroundImage:image forState:UIControlStateNormal];
// Make BarButton Item
UIBarButtonItem *navLeftButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = navLeftButton;
// this is the key entry to change the badgeValue
self.navigationItem.leftBarButtonItem.badgeValue = #"1";
I did something similar to MaxMa, but I just went ahead and added the badge directly to the self.navigationController.navigationBar.
MKNumberBadgeView *numberBadge = [[MKNumberBadgeView alloc] initWithFrame:CGRectMake(35, 0, 40, 40)];
numberBadge.value = 1;
[self.navigationController.navigationBar addSubview:numberBadge];
Just make sure to remove it from the subview during viewWillDisappear and add it back during viewDidAppear. It still seems a little hacky, but I'm more comfortable with this hack then changing the nav bar z-order.
To remove it during viewWillDisappear
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[numberBadge removeFromSuperview];
}
It's simple and the best way !
MKNumberBadgeView *numberBadge = [[MKNumberBadgeView alloc] initWithFrame:CGRectMake(230, -51, 40, 40)];
numberBadge.value = 5;
self.navigationController.navigationBar.layer.zPosition = -1;
[self.view addSubview:numberBadge];
Updated for Swift 3:
use below simple code to add the badge on UIBarButtonItem;
// Variable Declartion
var badgeCount = Int()
// Instance Method
func setUpBadgeCountAndBarButton() {
// badge label
let label = UILabel(frame: CGRect(x: 10, y: -05, width: 25, height: 25))
label.layer.borderColor = UIColor.clear.cgColor
label.layer.borderWidth = 2
label.layer.cornerRadius = label.bounds.size.height / 2
label.textAlignment = .center
label.layer.masksToBounds = true
label.textColor = .white
label.font = label.font.withSize(12)
label.backgroundColor = .red
label.text = "\(self.badgeCount)"
// button
let rightButton = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
rightButton.setBackgroundImage(UIImage(named: "notification_dash"), for: .normal)
rightButton.addTarget(self, action: #selector(notificationBarButtonClick), for: .touchUpInside)
rightButton.addSubview(label)
// Bar button item
let rightBarButtomItem = UIBarButtonItem(customView: rightButton)
navigationItem.rightBarButtonItem = rightBarButtomItem
}
// Call To Method
self.badgeCount = 11
self.setUpBadgeCountAndBarButton()
//Note: Increase your badge as per you received notification.You have to write your code as per your decided your logic i.e. how to maintain that badge count number in database.
Enjoy..!
I know this has been solved already,but I thought I might add what I have discovered to this answer for the sake of completeness.
You can also just add MKNumberBadgeView directly to the view for the UIBarButtonItem. Using Monotouch (C#), this is how you get the view for the UIBarButtonItem
//barbutton is some UIBarButtonItem. Make sure to check for view. In
//ViewDidLoad(), the view for the barbutton might not exist yet.
Selector sel = new Selector("view");
var handle = Messaging.intptr_objc_msgSend(barbutton.Handle, sel.Handle);
var view = Runtime.GetNSObject(handle) as UIView;
var mkBadge = ... //the badge
view.Add(badge);
view.Layer.ZPosition = <some large number>
I'm sure it's easy to convert this to Obj-C. You will also need to play around with the Frame for the badge to get it to show up in the right place.
This way you wont have to remove/add the view from the navigationbar.
After searching too many solutions I found this best solution for Objective-C
Goto Following Link and download two files "UIBarButtonItem+Badge.h" and "UIBarButtonItem+Badge.m" and add to your project :
https://github.com/mikeMTOL/UIBarButtonItem-Badge
Then import in your class :
#import "UIBarButtonItem+Badge.h"
And write down following line to add badge :
self.navigationItem.rightBarButtonItem.badgeValue = #"1"; //your value
Hope it will Work !!!
Here is a simple Swift 4 solution for it (with some customisation) https://github.com/Syngmaster/BadgedBarButtonItem
Just drag and drop the class into your project and you can use it like that:
class ViewController: UIViewController {
let btn = BadgedButtonItem(with: UIImage(named: "your_image"))
override func viewDidLoad() {
super.viewDidLoad()
btn.badgeTextColor = .black
btn.badgeTintColor = .yellow
btn.position = .right
btn.hasBorder = true
btn.borderColor = .red
btn.badgeSize = .medium
btn.badgeAnimation = true
self.navigationItem.rightBarButtonItem = btn
btn.tapAction = {
self.btn.setBadge(with: 4)
}
}
}
Extension to add an UIActivityIndicatorView without replacing the UIBarButtonItem.
extension UIBarButtonItem {
func startLoading() {
guard let view = self.value(forKey: "view") as? UIView else { return }
let loading = UIActivityIndicatorView(activityIndicatorStyle: .gray)
loading.frame = view.bounds
loading.startAnimating()
view.addSubview(loading)
view.bringSubview(toFront: loading)
let buttonView = view.subviews.first
buttonView?.alpha = 0.1
}
func stopLoading() {
guard let view = self.value(forKey: "view") as? UIView else { return }
let loading = view.subviews.filter({ $0 is UIActivityIndicatorView }).first
loading?.removeFromSuperview()
let buttonView = view.subviews.first
buttonView?.alpha = 1.0
}
}

Resources