My back button cannot exit my app - ios

I am now using my navigation Item to create exit button (left navigation item). When it comes to creating the view controller embed in navigation view controller , it seems that we cannot exit the app by using popViewControllerAnimated and dismissViewControllerAnimated . WOuld you please tell me what to do ?
The below is my code for embed view controller
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
navigationBar = self.navigationController.navigationBar;
[navigationBar setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor], NSForegroundColorAttributeName,
[UIFont fontWithName:#"TitilliumText22L-Medium" size:22.0], NSFontAttributeName,
nil] ];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:#"TEST SSS"];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 30)];
[button setImage:[UIImage imageNamed:#"menu_back.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *buttonItemA = [[UIBarButtonItem alloc] initWithCustomView:button];
navigationItem.leftBarButtonItem = buttonItemA;
UIButton *buttonA = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 88, 30)];
[buttonA setImage:[UIImage imageNamed:#"sss.png"] forState:UIControlStateNormal];
UIBarButtonItem *buttonItemB = [[UIBarButtonItem alloc] initWithCustomView:buttonA];
navigationItem.rightBarButtonItem = buttonItemB;
[navigationBar pushNavigationItem:navigationItem animated:NO];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonClicked:(id)sender {
NSLog(#"ssd finish");
[self.navigationController popViewControllerAnimated:YES|NO];
}
#end

Please read the document on this link, Apple Q&A Link for quit iOS app
This should answer your question:-
Go to your info.plist and check the key
"Application does not run in background"
and set it to :- "TRUE"
Then the time user presses the home button, the application exits completely.
OR as the link suggests pop an alert so that the user will know what to do for exiting the app.

Related

reusable UIBarButtonItem in all View Controllers in Objective C

I making custom navigationBar with background color and font size. In addition i have add menu button on right. For this I had made the category named
UINavigationController+Transparent.h
#interface UINavigationController (Transparent)
- (void)presentTransparentNavigationBar;
- (void)hideTransparentNavigationBar;
#end
UINavigationController+Transparent.m
#import "UINavigationController+Transparent.h"
#implementation UINavigationController (Transparent)
UIBarButtonItem *menuButton;
- (void)presentTransparentNavigationBar;
{
menuButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu_icon"] style:UIBarButtonItemStylePlain target:self action:#selector(showMenu:)];
[menuButton setTintColor:[UIColor whiteColor]];
self.navigationItem.rightBarButtonItem = menuButton;
UIImage *backButtonImage = [UIImage imageNamed:#"back"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:backButtonImage
forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
[backButton addTarget:self
action:#selector(popViewController)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
[self.navigationBar setTranslucent:NO];
[self.navigationBar setShadowImage:[UIImage new]];
[self.navigationBar setBarTintColor:[UIColor wolfRed]];
[self.navigationBar setTitleTextAttributes:
#{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont fontWithName:#"Helvetica" size:19.0] }];
[self setNavigationBarHidden:NO animated:NO];
}
- (void)hideTransparentNavigationBar
{
[self setNavigationBarHidden:YES animated:NO];
[self.navigationBar setBackgroundImage:[[UINavigationBar appearance] backgroundImageForBarMetrics:UIBarMetricsDefault] forBarMetrics:UIBarMetricsDefault];
[self.navigationBar setTranslucent:[[UINavigationBar appearance] isTranslucent]];
[self.navigationBar setShadowImage:[[UINavigationBar appearance] shadowImage]];
}
#end
inside my ViewControllers i call
[self.navigationController presentTransparentNavigationBar];
or
[self.navigationController hideTransparentNavigationBar];
The problem is that menu button is not visible and back button is seems like standard iOS blue back button.
Thanks for help!
See I used to customize my navigation bar in following way with
objective c
Step.1 Make sure your View Controller is embed in Navigation Controller
Step.2 Add required icons in your assets eg. "menu_icon" and "back"
Step.3 with the objective-C you can customize navigation bar as like you want.
I always do this way,
#import "ViewController.h"
#interface ViewController (){UIBarButtonItem *menuButton;}
#end
#implementation ViewController
#pragma mark - life cycle methods
- (void)viewDidLoad {[super viewDidLoad];}
- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];}
#pragma mark - IBAction methods
- (IBAction)showClicked:(id)sender {[self presentTransparentNavigationBar];}
- (IBAction)hideClicked:(id)sender {[self hideTransparentNavigationBar];}
#pragma mark - Navigation Bar methods
//Customize Naviagtion Bar
- (void)presentTransparentNavigationBar;
{
//Add Menu Button to Navigaiton Bar
menuButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu_icon"] style:UIBarButtonItemStylePlain target:self action:#selector(showMenu:)];
[menuButton setTintColor:[UIColor whiteColor]];
self.navigationItem.rightBarButtonItem = menuButton;
//Add Back button to Navigation Bar
UIImage *backButtonImage = [UIImage imageNamed:#"back"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:backButtonImage
forState:UIControlStateNormal];
backButton.frame = CGRectMake(0, 0, backButtonImage.size.width, backButtonImage.size.height);
[backButton addTarget:self
action:#selector(popViewController)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
//Config Navigaton bar settings
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
[self.navigationController.navigationBar setBarTintColor:[UIColor lightGrayColor]];//I used light gray color
[self.navigationController.navigationBar setTitleTextAttributes:
#{NSForegroundColorAttributeName:[UIColor whiteColor], NSFontAttributeName:[UIFont fontWithName:#"Helvetica" size:19.0] }];
[self.navigationController.navigationBar setHidden:NO];
}
//Hide Navigation Bar
- (void)hideTransparentNavigationBar
{
[self.navigationController.navigationBar setHidden:YES];
[self.navigationController.navigationBar setBackgroundImage:[[UINavigationBar appearance] backgroundImageForBarMetrics:UIBarMetricsDefault] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setTranslucent:[[UINavigationBar appearance] isTranslucent]];
[self.navigationController.navigationBar setShadowImage:[[UINavigationBar appearance] shadowImage]];
}
- (void) showMenu:(id) sender{ /*TODO when clicks on Menu button */ }
- (void) popViewController{ /*TODO when clicks on Back button */ }
#end
and if managed everything proper you should be able to get Menu and Back button to navigation bar when you click show button on the screen.
Note:
you can do this in your AppDelegate file so it will available in entire application

backBarButtonItem not getting displayed

I know viewcontroller's navigation item's backBarButtonItem gets displayed when another view controller is pushed on stack and this is 2nd viewcontroller from top.
I have viewcontroller A which have following in viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = NO;
[self.navigationItem setBackBarButtonItem:[UIBarButtonItem itemWithImageNamed:#"ic_header_slide" selectedImage:nil target:nil action:nil]];
}
When I push viewcontroller B, this custom back button is not getting displayed, instead I see default back button which iOS creates.
A extends UITableViewController and B extends UIViewController. I am not setting leftBarButtonItem, leftBarButtonItems, rightBarButtonItem, rightBarButtonItems in any of these navigationItem.
EDIT
I have read about setting leftBarButtonItems. setting leftbarbuttonitems on B works. but I think setting backBarButtonItem on A is correct way of doing that. It is also mentioned in documentation but not working in my case. I want to ask whether there is bug in backBarButtonItem or I have some misunderstanding the way it works and I am not doing it correctly.
To hide the default back button of the navigation bar use,
self.navigationItem.hidesBackButton=TRUE;
Also use the following method to add the custom BarButtons,
- (NSArray*)getLeftNavButtons:(NSString*)image andTarget:(id)target andFrame:(CGRect)frame andSpace:(int)fixedSpace
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = frame;
button.clipsToBounds = YES;
[button setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[button addTarget:target action:#selector(leftNavBtnClicked) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc]initWithCustomView:button];
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7"))
{
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = fixedSpace;
return #[negativeSpacer,barButton];
}
else{
return #[barButton];
}
return #[barButton];
}
Just override the default
self.navigationItem.hidesBackButton = YES;
UIBarButtonItem *back = [[UIBarButtonItem alloc]init];
back.title = #"Pick Me";
back.image = #"Your image";
[self.navigationItem setLeftBarButtonItem:back];
Set Right Bar Button Item
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]init];
UIImage *img1=[UIImage imageNamed:#"edit"];
CGRect frameimg1 = CGRectMake(0, 0, img1.size.width, img1.size.height);
UIButton *signOut=[[UIButton alloc]initWithFrame:frameimg1];
[signOut setBackgroundImage:img1 forState:UIControlStateNormal];
[signOut addTarget:self action:#selector(btnEditClicked:)
forControlEvents:UIControlEventTouchUpInside];
// [signOut setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *barButton=[[UIBarButtonItem alloc]initWithCustomView:signOut];
self.navigationItem.rightBarButtonItem=barButton;
Set Left Bar Button Item
UIImage *img11=[UIImage imageNamed:#"home"];
CGRect frameimg11 = CGRectMake(0, 0, img11.size.width, img11.size.height);
UIButton *signOut1=[[UIButton alloc]initWithFrame:frameimg11];
[signOut1 setBackgroundImage:img11 forState:UIControlStateNormal];
[signOut1 addTarget:self action:#selector(showLeftMenuPressed:)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton1=[[UIBarButtonItem alloc]initWithCustomView:signOut1];
self.navigationItem.leftBarButtonItem=barButton1;
self.navigationController.navigationBar.barTintColor=ColorNav;
self.navigationController.navigationBar.translucent=FALSE;
Set Navigation Title & Color
self.title = titletext;
[[[self navigationController] navigationBar]setTitleTextAttributes:#{NSForegroundColorAttributeName: textColor}];

Go back to unvisited page on IOS

I am unfamiliar with IOS development, so probably a simple question: is it possible that the user presses the "back" button on the top, and go to a (so far) non-visited page?
Here is the picture:
On window "1" user presses a button, the next window is "2". But here, if user presses the "back" button, go to page "3" (which was never opened so far)?
Thanks
You can simply redefine the back button by creating a new one in your second view controller like this :
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 60.0f, 30.0f)];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton setTitleColor:self.view.tintColor forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(pushToNextController) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backButtonItem;
}
- (void)pushToNextController {
UIViewController *thirdViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"thirdViewController"];
[self.navigationController pushViewController:thirdViewController animated:YES];
}

iOS 7 custom back button

I want to use custom back button. in iOS 6 everything is perfect but iOS 7 is strange.
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:[[UIImage imageNamed:#"back_button_normal"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0, 0, 12.0)] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
first, it has no iOS 7 arrow and no background image.
(Russian locale)
then, if you press the button background image appears. Also i had background image set for UIControlStateHighlighted state and when you hold the button pressed highlighted image appears too. After any back button once pressed all back buttons have background image.
BUT! If you present modal view controller, dismiss it, then push any view controller - iOS 7 arrow will appear at every back button.
I use DP5. Is that a UIKit bug?
PS Also i tried to create back button manually, using UIBarButtonItem, set background image to it, then self.navigationItem.backBarButtonItem = barButtonItem; Did not help.
Then i tried to set background image to disabled state and change enabled property of my bar button item, did not help too.
This is not a bug, this how Back button looks in iOS 7. For example:
You should probably use the new concept for your application, and not to set background image for back button in iOS 7.
If you still want you back button have the same as it looked in iOS6 than you should probably create those back buttons manually:
- (void)loadView
{
[super loadView];
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 60.0f, 30.0f)];
UIImage *backImage = [[UIImage imageNamed:#"back_button_normal.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12.0f, 0, 12.0f)];
[backButton setBackgroundImage:backImage forState:UIControlStateNormal];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(popBack) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backButtonItem;
}
-(void) popBack {
[self.navigationController popViewControllerAnimated:YES];
}
Edit: Not to break Swipe Gesture (Here is a source)
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
The custom background image not appearing on the first push was fixed in iOS 7 GM.
To hide standard back indicator use this code:
if ([UINavigationBar instancesRespondToSelector:#selector(setBackIndicatorImage:)]) { // iOS 7
[navigationBarAppearance setBackIndicatorImage:[UIImage imageNamed:#"transparent_1px"]];
[navigationBarAppearance setBackIndicatorTransitionMaskImage:[UIImage imageNamed:#"transparent_1px"]];
}
The custom background image not appearing initially was not fixed in iOS7 GM or final, as far as I can tell. I see the same problem. It does seem to be an Apple bug; the private view Apple uses simply does not get a setNeedsDisplay call when it needs it on initial display. Doing anything to it which causes that call should fix it -- like pressing on it (which likely changes internal state so it calls setNeedsDisplay on itself), or bringing a modal up (which probably forces a redisplay of the entire view hierarchy on the next viewWillAppear: call).
Using leftBarItems instead also can work, but that may cause a lot of maintenance issues with existing code (some screens may have their own left items, expecting that when set back to nil they restore the original back item, for example).
As mentioned, ideally you would be able to change to a borderless look on iOS7, which means that the bug isn't really apparent (since there is no background image). For some iOS6/iOS7 transition situations though, that may be difficult (lots of screens, and/or the need to support older iOS versions for a while and too hard to have two looks implemented, and it doesn't look good borderless without other changes). If that's the case, the following patch should work:
#import <objc/runtime.h>
#implementation UINavigationBar (BackButtonDisplayFix)
+ (void)load
{
if ([UIDevice currentDevice].systemVersion.intValue >= 7)
{
/*
* We first try to simply add an override version of didAddSubview: to the class. If it
* fails, that means that the class already has its own override implementation of the method
* (which we are expecting in this case), so use a method-swap version instead.
*/
Method didAddMethod = class_getInstanceMethod(self, #selector(_displaybugfixsuper_didAddSubview:));
if (!class_addMethod(self, #selector(didAddSubview:),
method_getImplementation(didAddMethod),
method_getTypeEncoding(didAddMethod)))
{
Method existMethod = class_getInstanceMethod(self, #selector(didAddSubview:));
Method replacement = class_getInstanceMethod(self, #selector(_displaybugfix_didAddSubview:));
method_exchangeImplementations(existMethod, replacement);
}
}
}
- (void)_displaybugfixsuper_didAddSubview:(UIView *)subview
{
[super didAddSubview:subview];
[subview setNeedsDisplay];
}
- (void)_displaybugfix_didAddSubview:(UIView *)subview
{
[self _displaybugfix_didAddSubview:subview]; // calls the existing method
[subview setNeedsDisplay];
}
#end
Note: UINavigationBar does currently have an override of the method in question, so I'd expect the method_exchangeImplementations style to be used. I just added the other stuff for safety in case Apple changes their code. We may go borderless ourselves, but I did find this approach worked as an option (until a more thorough UI uplift), at least.
Additional note: This bug appears to be fixed in iOS 7.1. So, the patch could be conditionalized to only install the methods if running >= 7.0 and < 7.1.
There is a better solution that doesn't involve method swizzling.
You need to add UINavigationViewControllerDelegate method somewhere in your app.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
dispatch_async(dispatch_get_main_queue(), ^{
[[navigationController.navigationBar subviews] makeObjectsPerformSelector:#selector(setNeedsDisplay)];
});
}
My solution is for iOS 7 and above.
At first, make default back button invisible.
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
then, set default backIndicatorImage of back button using custom image.
[UINavigationBar appearance].backIndicatorImage = [[UIImage imageNamed:#"topbar_icon_back_n.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorTransitionMaskImage = [[UIImage imageNamed:#"topbar_icon_back_p.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
At this point, make custom UINavigationBar for resizing _UINavigationBarBackIndicatorView which contains above backIndicatorImage.
const CGPoint SANavigationBarOffset = {-8, 11.5};
#implementation SANavigationBar
- (void)layoutSubviews
{
[super layoutSubviews];
// set back button position
NSArray *classNamesToReposition = #[#"_UINavigationBarBackIndicatorView"];
for (UIView *view in [self subviews]) {
if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) {
CGRect frame = [view frame];
frame.origin.x = 0;
frame.origin.y = 0;
[view setFrame:frame];
}
}
}
#end
then, set it as my navigationBar
// set custom NavagationBar for back button position
[self.navigationController setValue:[[SANavigationBar alloc] init] forKey:#"navigationBar"];
Add button as navigation item in ios7 as below
UIButton *btnAdd = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 60, 30)];
[btnAdd setContentMode:UIViewContentModeScaleAspectFit];
[btnAdd setBackgroundImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
[btnAdd addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *btnAdd = [[UIBarButtonItem alloc] initWithCustomView:imView];
self.navigationItem.rightBarButtonItem = btnAdd;
Using Swift you can just add a extension:
extension UIViewController: UIGestureRecognizerDelegate {
func popBack() {
self.navigationController?.popViewControllerAnimated(true)
}
func enableCustomBackButtom() {
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon-back"), style: UIBarButtonItemStyle.Plain, target: self, action:"popBack")
self.navigationController?.interactivePopGestureRecognizer.delegate = self
}
}
And in your UIViewController use like this:
self.enableCustomBackButtom()
I just did it providing the same behaviour as in iOS6 (notice that navigationBar is the UINavigationBar), make sure that navigationBar has a topItem
UINavigationItem *topItemNavigation = [navigationBar topItem];
UIBarButtonItem *barButtonTopItemNavigation = [[UIBarButtonItem alloc] initWithTitle:topItemNavigation.title style:UIBarButtonItemStyleBordered target:nil action:nil];
[barButtonTopItemNavigation setBackButtonBackgroundImage:YOUR_IMAGE_BACKGROUND forState:UIControlStateNormal barMetrics:UIBarMetricsDefault ];
[topItemNavigation setBackBarButtonItem: barButtonTopItemNavigation];
}
My solution was to write a category on UINavigationItem. This is for iOS7.
- (void)mdSetCustomBackButton:(UINavigationController *)navigationController
{
MDBackButton *backButton = [[MDBackButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 44.0, 44.0) navigationController:navigationController];
[backButton addTarget:self action:#selector(popBack:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
[self setLeftBarButtonItem:barButtonItem];
[navigationController.interactivePopGestureRecognizer setDelegate:(id<UIGestureRecognizerDelegate>)self];
}
- (void)popBack:(MDBackButton *)sender
{
[sender.navigationController popViewControllerAnimated:YES];
}
And subclass UIButton to add a UINavigationController property (to pop and set swipe back delegate).
#property (nonatomic, weak) UINavigationController *navigationController;
#implementation MDBackButton
- (id)initWithFrame:(CGRect)frame navigationController:(UINavigationController *)navigationController
{
self = [super initWithFrame:frame];
if(self){
_navigationController = navigationController;
[self setImage:[UIImage imageNamed:#"back_button"] forState:UIControlStateNormal];
}
return self;
}
This is work for me:
- (void)setCustomNavigationBackButton
{
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
UIImage *myIcon = [self imageWithImage:[UIImage imageNamed:#"backbutton.png"] scaledToSize:CGSizeMake(20, 20)];
self.navigationController.navigationBar.backIndicatorImage = myIcon;
self.navigationController.navigationBar.backIndicatorTransitionMaskImage = myIcon;
}
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
//UIGraphicsBeginImageContext(newSize);
// In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
// Pass 1.0 to force exact pixel size.
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Also, custom font with custom color:
//self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:
#{NSForegroundColorAttributeName:[UIColor whiteColor],
NSFontAttributeName:[UIFont fontWithName:#"Signika-Bold" size:20]}
forState:UIControlStateNormal];
Reference: https://stackoverflow.com/a/2658801/1371949
I use these codes below, which works in iOS 8
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
button.exclusiveTouch = YES;
button.titleLabel.font = [UIFont systemFontOfSize:14.0];
[button setTitleColor:kWhiteColor forState:UIControlStateNormal];
[button setTitleColor:[UIColor colorWithRed:1/255.0 green:36/255.0 blue:60/255.0 alpha:1.0] forState:UIControlStateHighlighted];
[button setTitle:#"Back" forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"barbutton_back"] forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)];
CGSize fontSize = [button.titleLabel sizeThatFits:CGSizeMake(100.0, 30.0)];
button.frame = CGRectMake(0.0, 0.0, button.imageView.image.size.width+fontSize.width, 30.0);
UIBarButtonItem *barbtn = [[UIBarButtonItem alloc] initWithCustomView:button];
//fix iOS 7 left margin
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSpacer.width = -10;
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:negativeSpacer,barbtn, nil];
-(void) viewWillAppear:(BOOL)animated
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0, 0, 30, 44)];
[btn setImage:[UIImage imageNamed:#"btnBack.png"] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(PopToView) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *btnBack = [[UIBarButtonItem alloc] initWithCustomView:btn];
[btnBack setTintColor:[UIColor whiteColor]];
[[self.navigationController navigationItem] setLeftBarButtonItem:btnBack];
}

UIBarButtonItem with custom image and no border

I want to create a UIBarButtonItem with a custom image, but I don't want the border that iPhone adds, as my Image has a special border.
It's the same as the back button but a forward button.
This App is for an inHouse project, so I don't care if Apple reject or approves it or likes it :-)
If I use the initWithCustomView:v property of the UIBarButtonItem, I can do it:
UIImage *image = [UIImage imageNamed:#"right.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage: [image stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateNormal];
[button setBackgroundImage: [[UIImage imageNamed: #"right_clicked.png"] stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateHighlighted];
button.frame= CGRectMake(0.0, 0.0, image.size.width, image.size.height);
[button addTarget:self action:#selector(AcceptData) forControlEvents:UIControlEventTouchUpInside];
UIView *v=[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height) ];
[v addSubview:button];
UIBarButtonItem *forward = [[UIBarButtonItem alloc] initWithCustomView:v];
self.navigationItem.rightBarButtonItem= forward;
[v release];
[image release];
This works, but if I have to repeat this process in 10 views, this is not DRY.
I suppose I have to subclass, but what ?
NSView ?
UIBarButtonItem ?
thanks,
regards,
Another simple solution is
Drag a standard UIButton
Set the button's style to custom and set your image for that button
Drag it onto the UINavigationBar
Set Selector
You can add a method to UIBarButtonItem without subclassing it using custom category:
#interface UIBarButtonItem(MyCategory)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;
#end
#implementation UIBarButtonItem(MyCategory)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action{
// Move your item creation code here
}
#end
So anywhere in your code you can create bar item calling this method (provided that you include a header with its declaration).
P.S. You do not need to use 'v' UIView as you can create UIBarButtonItem with a button as custom view directly.
P.P.S. You also need [forward release] in your code.
I found it this ways easy. It is sugested on top. "random.png" has to be in project. Just drag and drop any image.
UIButton *a1 = [UIButton buttonWithType:UIButtonTypeCustom];
[a1 setFrame:CGRectMake(0.0f, 0.0f, 25.0f, 25.0f)];
[a1 addTarget:self action:#selector(randomMsg) forControlEvents:UIControlEventTouchUpInside];
[a1 setImage:[UIImage imageNamed:#"config.png"] forState:UIControlStateNormal];
UIBarButtonItem *random = [[UIBarButtonItem alloc] initWithCustomView:a1];
//? line incomplete ?// imageNamed:#"random.png"] style:UIBarButtonItemStylePlain target:self action:#selector(randomMsg)];
self.navigationItem.rightBarButtonItem = random;
An alternative is to subclass UIBarButtonItem. Why? So that the action is invoked on the target with the correct sender. In the code above, the sender argument in the action message is the UIButton instance, not the UIBarButtonItem instance. This would be important, for example, if you wish to present a UIPopoverController from the bar button item. By subclassing UIBarButtonItem, you can add an ivar that retains the original target, allowing our subclass instances to intercept, modify, and forward the action message with the proper sender.
So, CCFBarButtonItem.h:
#import <uIKit/UIBarButtonItem.h>
#interface CCFBarButtonItem : UIBarButtonItem
{
#protected
id _originalTarget;
}
- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
#end
and CCFBarButtonItem.m
#import "CCFBarButtonItem.h"
#import <UIKit/UIButton.h>
#import <UIKit/UIView.h>
#import <UIKit/UIImage.h>
#implementation CCFBarButtonItem
#pragma mark - Object life cycle
- (id)initWithImage:(UIImage *)image target:(id)target action:(SEL)action;
{
_ASSIGN( _originalTarget, target );
UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
[imgButton setImage:image forState:UIControlStateNormal];
imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
[imgButton addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
self = [super initWithCustomView:imgButton];
return self;
}
- (void)dealloc;
{
MCRelease(_originalTarget);
[super dealloc];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
{
if( [_originalTarget respondsToSelector:aSelector] )
{
return [_originalTarget methodSignatureForSelector:aSelector];
}
else
{
return [super methodSignatureForSelector:aSelector];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation;
{
SEL aSelector = [anInvocation selector];
if( [_originalTarget respondsToSelector:aSelector] )
{
// modify the 'sender' argument so that it points to self
[anInvocation setArgument:&self atIndex:2];
[anInvocation invokeWithTarget:_originalTarget];
}
else
{
[self doesNotRecognizeSelector:aSelector];
}
}
#end
UIBarButtonItem *menuItem = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:#"icon-menu.png"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(showMenu)];
This can also be done programmatically as well (of-course):
First, create a custom view. This custom view can contain an image, button or whatever else you would like. The custom view can be made programmatically or in IB:
UIImage *customImage = [UIImage imageNamed:#"imageName"];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, customImage.size.width, customImage.size.height)];
customView.backgroundColor = [UIColor colorWithPatternImage:customImage];
Next, create a UIBarButtonItem and initialize it with the custom view.
UIBarButtonItem *customBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:customView];
Now, just add the custom UIBarButton to the leftBarButtonItem:
self.navigationItem.leftBarButtonItem = customBarButtonItem;
Ok that category works very good because there are no problems with Popovercontroller :-)
#import <UIKit/UIKit.h>
#interface UIBarButtonItem (BarButtonItemExtended)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action;
-(void)performBarButtonAction:(id)sender;
#end
#import "UIBarButtonItem+BarButtonItemExtended.h"
#implementation UIBarButtonItem (BarButtonItemExtended)
+ (UIBarButtonItem*)barItemWithImage:(UIImage*)image target:(id)target action:(SEL)action
{
UIButton *imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
[imgButton setImage:image forState:UIControlStateNormal];
imgButton.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
UIBarButtonItem *b = [[UIBarButtonItem alloc]initWithCustomView:imgButton];
[imgButton addTarget:b action:#selector(performBarButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[b setAction:action];
[b setTarget:target];
return b;
}
-(void)performBarButtonAction:(UIButton*)sender
{
[[self target] performSelector:self.action withObject:self];
}
#end
One another solution, think it's simpler in case when creating button programatically:
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:defaultImage
landscapeImagePhone:landscapeImage
style:UIBarButtonItemStylePlain
target:self
action:#selector(someSelector)];
[button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[button setBackgroundImage:[UIImage new] forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
Check this out simple solution.
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.image = [UIImage imageNamed:#"navButton.png"];
barButtonItem.style = UIBarButtonItemStylePlain;
[barButtonItem setBackgroundImage:[UIImage imageNamed:#"1x1.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
Here 1x1.png is a 1 pixel transparent png image which you can download from the link below
http://commons.wikimedia.org/wiki/File:1x1.png

Resources