How to add Badges on UIBarbutton item? - ios

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
}
}

Related

Update UIBarButtonItem within view controller

I'm trying to update UIBarButtonItem tint color from a view controller but nothing has changed. Can't we access the UIBarButtonItem within view controller using self.navigationItem.rightBarButtonItem?
[UIView animateWithDuration:.8 delay:0.5 options:UIViewAnimationOptionAllowUserInteraction animations:^ {
//button.alpha = .01; //don't animate alpha to 0, otherwise you won't be able to interact with it
self.navigationItem.rightBarButtonItem.tintColor = [UIColor whiteColor];
} completion:^(BOOL finished) {
self.navigationItem.rightBarButtonItem.tintColor = [UIColor whiteColor];
}];
I have tried your problem by making outlet of UIBarButtonItem. It is working fine. You can set the tint color by direct refrence.
Here is the code
class ViewController: UIViewController {
#IBOutlet weak var addItem: UIBarButtonItem!
var username = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func addItem(_ sender: UIBarButtonItem) {
UIView.animate(withDuration: 20) {
self.addItem.tintColor = UIColor.red
}
}
}
let addButton = UIButton(type: .custom)
addButton.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
addButton.tintColor = UIColor.gray
let addMoreItem = UIBarButtonItem(customView: addButton)
self.navigationItem.rightBarButtonItem = addMoreItem
it may be work for you.
UIButton *btnBack = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[btnback setTintColor:[UIColor whiteColor]];
[btnBack addTarget:self action:#selector(onClickBtnBack:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
self.navigationItem.rightBarButtonItem = barButtonItem;
also you can set background color and text color.

How to add the UISegmentedControl in UINavigationBar?

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.

How can I change the background color of a UIBarButtonItem on iOS 7+?

I'd like to indicate that a particular UIBarButtonItem is toggled on or off by changing its background color. Mobile Safari uses this feature to indicate whether private browsing is on or off:
How can I do this, since there's no backgroundColor property on UIBarButtonItem?
Create a UIButton and use it as the custom view for the UIBarButtonItem. Then, set the backgroundColor on the button's layer:
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTitle:#"Test"];
button.layer.backgroundColor = [UIColor redColor].CGColor;
button.layer.cornerRadius = 4.0;
UIBarButtonItem* buttonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.toolbarItems = #[buttonItem];
You could instead just use two images. One for selected and one for unselected
- (void)setBackgroundImage:(UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics
The above function should help you do this
Swift 5 Answer
let rightBarCancelButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
let cancelImage = UIImage(systemName: "multiply")
rightBarCancelButton.setImage(cancelImage, for: .normal)
rightBarCancelButton.layer.cornerRadius = 15
rightBarCancelButton.backgroundColor = UIColor.lightGray
let rightBarButton = UIBarButtonItem(customView: rightBarCancelButton)
navigationItem.rightBarButtonItem = rightBarButton
Works like a charm!

How to put a badge on customized UIBarButtonItem

I have a navigation bar with two buttons, one is a back button the other a chat symbol.
I write this code like this:
UIBarButtonItem *_btn=[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"back.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(goBackToPreviousView)];
self.navigationItem.leftBarButtonItem=_btn;
self.navigationItem.leftBarButtonItem.tintColor = [UIColor blackColor];
UIBarButtonItem *_btn2=[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"chat.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(startChat)];
self.navigationItem.rightBarButtonItem=_btn2;
self.navigationItem.rightBarButtonItem.tintColor = [Utility colorWithHexValue:CyanBlue];
The problem I have is that whenever there is some new messages in the chat that I have not seen, there should be like a badge of some sort, or a customized label over the chat button, to indicate how many new messages you have.
How do I do this?
for Swift 3.0:
Result:
Code:
override func viewDidLoad() {
super.viewDidLoad()
// badge label
let label = UILabel(frame: CGRect(x: 10, y: -10, width: 20, height: 20))
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.font = UIFont(name: "SanFranciscoText-Light", size: 13)
label.textColor = .white
label.backgroundColor = .red
label.text = "80"
// button
let rightButton = UIButton(frame: CGRect(x: 0, y: 0, width: 18, height: 16))
rightButton.setBackgroundImage(UIImage(named: "inbox"), for: .normal)
rightButton.addTarget(self, action: #selector(rightButtonTouched), for: .touchUpInside)
rightButton.addSubview(label)
// Bar button item
let rightBarButtomItem = UIBarButtonItem(customView: rightButton)
navigationItem.rightBarButtonItem = rightBarButtomItem
}
func rightButtonTouched() {
print("right button touched")
}
in iOS 8 - I was able to do it by changing the badgeValue
self.messageButton.badgeValue = #"5";
where message button is a UIBarButton
You have to include these two files to your xcode
UIBarButtonItem+Badge.h
UIBarButtonItem+Badge.m
which can be found here
Github link to files
You can try this piece of code:-
UILabel *badgeLbl = [[UILabel alloc]initWithFrame:CGRectMake(16, -2, 18, 18)];
badgeLbl.backgroundColor = [UIColor whiteColor];
badgeLbl.textColor = [UIColor blackColor];
badgeLbl.textAlignment = NSTextAlignmentCenter;
badgeLbl.layer.cornerRadius = 9.0;
badgeLbl.layer.masksToBounds = true;
badgeLbl.text = #"10";
UIButton *notificationBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 35, 35)];
[notificationBtn setBackgroundImage:[UIImage imageNamed:#"image_name"] forState:UIControlStateNormal];
[notificationBtn setTitle:#"" forState:UIControlStateNormal];
[notificationBtn addTarget:self action:#selector(onClickAction:) forControlEvents:UIControlEventTouchUpInside];
[notificationBtn addSubview:badgeLbl];
UIBarButtonItem *notificationBarBtn = [[UIBarButtonItem alloc]initWithCustomView:notificationBtn];
self.navigationItem.rightBarButtonItem = notificationBarBtn;
Good day!
Here is my version - easy and without any problems:
navBar = [[UINavigationBar alloc] initWithFrame: CGRectMake(0, 0, self.view.frame.size.width, 64)];
[self.view addSubview:navBar];
navItem = [[UINavigationItem alloc] initWithTitle:NSLocalizedString(#"Meetings", nil)];
[navBar pushNavigationItem:navItem animated:NO];
UIButton *chat = [UIButton buttonWithType: UIButtonTypeRoundedRect];
[chat setTitle:#"Chat" forState: UIControlStateNormal];
UILabel *badge = [[UILabel alloc] initWithFrame: CGRectMake(0, 0, 20, 20)];
badge.textColor = [UIColor darkGrayColor];
badge.font = [UIFont fontWithName: fontName size: 15];
badge.text = #"10";
badge.textAlignment = NSTextAlignmentCenter;
badge.layer.cornerRadius = 10.0f;
badge.layer.backgroundColor = [UIColor yellowColor].CGColor;
badge.clipsToBounds = YES;
badge.center = CGPointMake(50, 20);
[chat addSubview: badge];
navItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView: chat];
have a nice day!
try custom methods
https://github.com/TanguyAladenise/BBBadgeBarButtonItem
http://yuvarajmanickam.wordpress.com/2012/02/01/add-badges-on-uibarbuttonitem-in-iphone-app/
How to add Badges on UIBarbutton item?
https://www.cocoacontrols.com/controls/mknumberbadgeview
You can try this category
UIBarButtonItem-Badge
Try this customized control - mknumberbadgeview

Add border in UIBarButtonItem

In my app, I have designed a view in the interface builder.
This view has a toolbar, with some UIBarButtonItem in.
My buttons can be custom images, or default button like share, add,...
Now with iOS7, buttons don't have anymore borders. So I'd like to add some.
Here is what i want to do : add borders like the white lines on my screenshot.
What I've tried is to add a UIButton to the toolbar. In my example, I've set my back button size (12x44). I add this button as a IBOutlet property of my view controller, and try to draw a border to it :
CALayer *cancelBorder = [CALayer layer];
[cancelBorder setFrame:CGRectMake(12, 0, 1, 44)];
[backBorder setBackgroundColor:[[UIColor whiteColor] CGColor]];
[backButton.layer addSublayer:cancelBorder];
But it doesn't work. Anyone has a solution?
Adding UIBarButtonItem to toolbar programmatically may solve your problem.
First, create custom button with images, borders, etc. As HereTrix said, you can add border to this button.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(10, 0, 30, 30);
button.layer.borderColor = [UIColor blueColor].CGColor;
button.layer.borderWidth = 1.0f;
/* any other button customization */
Then, initialize UIBarButtonItem with that custom button and add this item to your toolbar.
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.toolBar.items = #[backButton];
Swift 3 : Below is my full implementation for button customization and event handling.
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.init(type: .custom)
button.setTitle("Tester", for: .normal)
button.setTitleColor(.darkGray, for: .normal)
button.layer.borderWidth = 1
button.layer.cornerRadius = 5
button.layer.borderColor = UIColor.darkGray.cgColor
button.addTarget(self, action: #selector(self.handleButton), for: .touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let button = self.navigationItem.rightBarButtonItem?.customView {
button.frame = CGRect(x:0, y:0, width:80, height:34)
}
}
func handleButton( sender : UIButton ) {
// It would be nice is isEnabled worked...
sender.alpha = sender.alpha == 1.0 ? 0.5 : 1.0
}
Hope this helps

Resources