UINavigationItems Stretching in iOS11 - uinavigationbar

I'm updating an app to ensure that it works as expected in iOS11. The only issue I've run into is that the navigation bar looks quite different in iOS11. The position of the elements and size is not the same between versions. I've looked at my code and i'm explicitly setting frame sizes and edge insets, why are these values are not respected in iOS11?
//-- Create Right Navigation Item Buttons
// create kabob btn
UIButton *kabobBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[kabobBtn addTarget:self action:#selector(viewUsersClicked:)forControlEvents:UIControlEventTouchUpInside];
kabobBtn.clipsToBounds = YES;
[kabobBtn setImage:[UIImage imageNamed:#"KabobMenu2_0071bc_Right.png"]
forState:UIControlStateNormal];
[kabobBtn.imageView setContentMode:UIViewContentModeScaleAspectFit];
[kabobBtn setFrame:CGRectMake(0, 0, 32, 32)];
// create user profile button
UIButton *userBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[userBtn setImage:[UIImage imageNamed:#"people.png"]
forState:UIControlStateNormal];
[userBtn addTarget:self action:#selector(viewUserProfileClicked:)forControlEvents:UIControlEventTouchUpInside];
[userBtn setFrame:CGRectMake(0, 0, 38, 38)];
userBtn.clipsToBounds = YES;
[userBtn.layer setCornerRadius:(38/2)];
[userBtn.layer setMasksToBounds:YES];
[userBtn.layer setBorderColor:[[UIColor blackColor]CGColor]];
[userBtn.layer setBorderWidth:1];
self.userPictureURL = [defaults objectForKey:#"userPicture"];
[userBtn setImage:[UIImage imageNamed:#"defaultUserImage.png"] forState:UIControlStateNormal];
[userBtn setContentMode:UIViewContentModeScaleAspectFill];
[userBtn setBackgroundColor:[UIColor clearColor]];
// add buttons to bar button items
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:kabobBtn];
UIBarButtonItem *barButton2 = [[UIBarButtonItem alloc] initWithCustomView:userBtn];
// add bar button items to right bar button item array
self.navigationItem.rightBarButtonItems = #[barButton,barButton2];
//-- Create Left Hamburger Button
UIButton *customOpen = [UIButton buttonWithType:UIButtonTypeCustom];
[customOpen setFrame:CGRectMake(0, 0, 30, 44)];
[customOpen setImage:[UIImage imageNamed:#"hamburger.png"] forState:UIControlStateNormal];
[customOpen setImageEdgeInsets:UIEdgeInsetsMake(10, -5, 16, 10)];
UIBarButtonItem *openItem = [[UIBarButtonItem alloc] initWithCustomView:customOpen];
if(self.showHamburger){
self.navigationItem.leftBarButtonItem = openItem;
}else{
self.navigationItem.leftBarButtonItem = nil;
}

Apparently iOS 11 uses autolayout for nav bar buttons. Use auto layout constraints to set button width and height.
[userBtn.widthAnchor constraintEqualToConstant:38.f].active = YES;
[userBtn.heightAnchor constraintEqualToConstant:38.f].active = YES;
This should fix the stretching issue.
Thanks to this answer

Related

UINavigatiobar right barbutton item image not visible

I am creating a custom right bar button item for UINavigation bar. Here is the code I am using,
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
UIButton *backPageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backPageButton setFrame:CGRectMake(0, 0, 50, 30)];
[ backPageButton setImage:[UIImage imageNamed:#"left_arrow.png"] forState:UIControlStateNormal];
backPageButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
[backPageButton addTarget:self action:#selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
[backPageButton setUserInteractionEnabled:YES];
[container addSubview:backPageButton];
UIButton *forwardPageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[forwardPageButton setFrame:CGRectMake(30, 0, 50, 30)];
[ forwardPageButton setImage:[UIImage imageNamed:#"right_arrow.png"] forState:UIControlStateNormal];
[forwardPageButton addTarget:self action:#selector(forwardButtonAction) forControlEvents:UIControlEventTouchUpInside];
forwardPageButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
[forwardPageButton setUserInteractionEnabled:YES];
[container addSubview:forwardPageButton];
UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithCustomView:container];
// set the nav bar's right button item
self.navigationItem.rightBarButtonItem = item;
For some reason the button images are not visible. I added a background color to each button and can see that the buttons are actually added to navigation bar and also the click events are working fine. But button images are not visible.
How to fix it?
Thanks
Of course you've made a double check that images belong to your target?
To debug your views in runtime you could use small but very useful button in Xcode
more about this: https://developer.apple.com/library/ios/recipes/xcode_help-debugger/using_view_debugger/using_view_debugger.html

Custom UIBarButtonItem keep Aspect Ratio for Image but Space out Buttons

I am adding some custom image UIBarButtonItems to my navigation bar. If I do not mess with the item.width property, then my buttons are too close together, but if I space them out with the width property, then the button image is distorted. How can I maintain the aspect ratio of the button image but space out my custom items?
// Create custom map button
UIButton *mapButton = [UIButton buttonWithType:UIButtonTypeCustom];
[mapButton setImage:[UIImage imageNamed:#"map.png"] forState:UIControlStateNormal];
[mapButton addTarget:self action:#selector(dismissMapView:) forControlEvents:UIControlEventTouchUpInside];
[mapButton setFrame:CGRectMake(280, 25, 30, 30)];
UIBarButtonItem *button1 = [[UIBarButtonItem alloc] initWithCustomView:mapButton];
button1.width = (self.drawer.frame.size.width / 5.0f); // Space it out a bit
// Create custom list button
UIButton *listButton = [UIButton buttonWithType:UIButtonTypeCustom];
[listButton setImage:[UIImage imageNamed:#"list.png"] forState:UIControlStateNormal];
[listButton addTarget:self action:#selector(scrollToRow:) forControlEvents:UIControlEventTouchUpInside];
[listButton setFrame:CGRectMake(280, 25, 30, 30)];
UIBarButtonItem *button2 = [[UIBarButtonItem alloc] initWithCustomView:listButton];
button2.width = (self.drawer.frame.size.width / 5.0f); // Space it out a bit
// Add buttons to drawer
self.drawer.items = #[button1,button2];
Try this code for adding custom bar button in navigationbar.
UIImage* image3 = [UIImage imageNamed:#"compose_message_button.png"];
CGRect frameimg = CGRectMake(250, 9, 43,32);
UIButton *SettingButton = [[UIButton alloc] initWithFrame:frameimg];
[SettingButton setBackgroundImage:image3 forState:UIControlStateNormal];
[SettingButton addTarget:self action:#selector(BtnWriteMessage:)
forControlEvents:UIControlEventTouchUpInside];
[SettingButton setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *mailbutton =[[UIBarButtonItem alloc] initWithCustomView:SettingButton];
self.navigationItem.rightBarButtonItem=mailbutton;
[SettingButton release];
i hope this code is useful for you.
You can create some explicit spacer items using UIBarButtonSystemItemFixedSpace.
Or you could create your bar buttons with custom views (initWithCustomView:) and then you can lay the content views out as you like.

Navigation Bar custom button

backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton addTarget:self action:#selector(gotoAmphorasViewController) forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:CGRectMake(0.0f,0.0f, 44,44)];
The problem i am facing is that though the button dimensions are44*44, wherever i tap anywhere around it, the the button action is fired.
Please try the bellow code : its working properly
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *buttonImage = [UIImage imageNamed:#"back.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:buttonImage forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[button addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customBarItem;
[customBarItem release];
}
-(void)back {
[self.navigationController popViewControllerAnimated:YES];
}
Its not a bug. It is a default behaviour. In iPhone, for navigation bar buttons the touch detection is little more expanded rather than its frame. Just have a look on any other application. Everywhere the button get fired if we tap nearer but outside its frame.
It's the intended behaviour, if you really want to limit the area of the touch, you can wrap the button inside a UIView:
UIView *buttonContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[buttonContainer addSubview:button];
_barButton = [[UIBarButtonItem alloc] initWithCustomView:buttonContainer];

Add a back arrow to leftBarButtonItem?

I want to add a back arrow to a leftBarButtonItem, to make it appear visually as if it was a regular back button, although it's functionality is slightly different.
Is there a way to do this?
You can use custom button and hide the back button if you are using navigation controller.
To hide back button use this:
self.navigationItem.hidesBackButton = YES;
And for Custom Button:
UIButton * customButton = [UIButton buttonWithType:UIButtonTypeCustom];
[customButton setBackgroundColor:[UIColor colorWithRed:197.0/255.0 green:190.0/255.0 blue:157.0/255.0 alpha:1.0]];
[customButton setTitle:#"Do Something" forState:UIControlStateNormal];
customButton.titleLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:11.0f];
[customButton.layer setCornerRadius:3.0f];
[customButton.layer setMasksToBounds:YES];
[customButton.layer setBorderWidth:1.0f];
[customButton.layer setBorderColor: [[UIColor grayColor] CGColor]];
customButton.frame=CGRectMake(0.0, 100.0, 50.0, 25.0);
[customButton addTarget:self action:#selector(customMethod:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem * customItem = [[UIBarButtonItem alloc] initWithCustomView:customButton];
customItem.tintColor=[UIColor blackColor];
self.navigationItem.leftBarButtonItem = customItem;
This will work for you.
Happy Coding
If you are using UINavigationController and then push new viewcontroller it will automatically show back button.
If you are Not Using UINavigationController than
Use Custom UIButton for that with back image
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 48, 37);
[backButton addTarget:self action:#selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
backButton.showsTouchWhenHighlighted = YES;
UIImage *backButtonImage = [UIImage imageNamed:#"back-button.png"];
[backButton setImage:backButtonImage forState:UIControlStateNormal];
backButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backBarButtonItem;
You can change the value for the frame and the imageEdgeInsets as per your requirements.
Refer this SO Answer.

UINavigationItem rightButton position is different on iOS6 vs iOS7 and missing touches

I am trying to make my uinavigationbar to align the same way as in the iOS6 version of my app. What I am finding is that on the iOS7 the uinavigationbar items are pulled in a bit towards the title. Also for example if you are hitting just a litle right of the uinavigationitem.rightButton, the hits are not registered, however if you hit left of it for atleast 20px you can get the hits. Can anyone help me with moving that touch area to the right as well?
Here is the code that I used to setup the button:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
rightButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
rightButton.imageEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 0);
rightButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
rightButton.frame = view.bounds;
rightButton.bounds = CGRectMake(0,0,44,44);
[view addSubview:rightButton];
[rightButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[rightButton setImage:[[UIImage imageNamed:imageName] imageWithOpacity:0.8] forState:UIControlStateHighlighted];
[rightButton addTarget:target action:sel forControlEvents:UIControlEventTouchUpInside];
navItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
Thanks,
Rajan
Use below code
UIImage *faceImage1= [UIImage imageNamed:#"slideshowarrow"];
UIButton *face1 = [UIButton buttonWithType:UIButtonTypeCustom];
face1.bounds = CGRectMake( 10, 0, faceImage1.size.width, faceImage1.size.height );
[face1 addTarget:self action:#selector(Goto_nextView) forControlEvents:UIControlEventTouchUpInside];
[face1 setImage:faceImage1 forState:UIControlStateNormal];
UIBarButtonItem *backButton1 = [[UIBarButtonItem alloc] initWithCustomView:face1];
self.navigationItem.rightBarButtonItem = backButton1;

Resources