I'm using Xcode 8.0.
I add a custom left barbutton to my NavBar:
UIImage * imageNormal = [UIImage imageNamed:#"InfoIcon"];
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(testPressed ) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:imageNormal forState:UIControlStateNormal];
// set the frame of the button
button.frame = CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height);
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, imageNormal.size.width, imageNormal.size.height)];
[view addSubview:button];
// set the barbuttonitem to be the view
UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.leftBarButtonItem = barButtonItem;
Here what I got:
unfortunately my button is not centered because the Nav bar has a custom image higher than the standard. But if I press the info Icon it works.
If I change the icon position with this line of code:
button.frame = CGRectMake(0, -30, imageNormal.size.width, imageNormal.size.height);
I got the right positioning:
But in this case the bar button is not anymore clickable, and I don't get why this is happening.
As workaround I attach a gesture to the view:
UITapGestureRecognizer *_tapOnVideoRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.revealViewController action:#selector(revealToggle:)];
[view addGestureRecognizer:_tapOnVideoRecognizer];
it works, but the tap is on the view and not on the button so that the changing status of the button when pressed is not working.
#JakubKnejzlik from https://stackoverflow.com/a/12554715/1320479
suggests:
This can be fixed by subclassing the wrapper view (superview of button, custom view of uibarbuttonitem) and overriding the hittest method to return button accordingly.
But I have no idea how to do it
Related
I've created custom back bar button. And I added an UIview because I have to change position of it within bar.
UIImage *backButtonImage = [UIImage imageNamed:#"backBtnWhite"];
_backButton = [UIButton buttonWithType:UIButtonTypeCustom];
_backButton.exclusiveTouch = YES;
[_backButton setImage:backButtonImage forState:UIControlStateNormal];
[_backButton setImage:backButtonImage forState:UIControlStateHighlighted];
[_backButton addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
_backButton.frame = CGRectMake(-4.0, 7.0, 40, 40);
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(-4.0, 7.0, backButtonImage.size.width, backButtonImage.size.height)];
[view addSubview:_backButton];
UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:view];
self.navigationItem.rightBarButtonItem = barButtonItem;
But after that I've added UIView it became difficult to click on it.
I've tried to change button area, but it didn't give results.
It seems like you specify incorrect frame for _button or/and view and this changes the tap region. Try to set different background color for _backButton and view. This will show you if frames are in positions that you expect.
If you try to adjust image position by specifying these frames - its more correct to use properties of UIButton like imageEdgeInsets and titleEdgeInsets.
Here is my navigation bar
I had a problem about changing vertical position of Settings UIBarButtonItem on my navigation bar. I would like to move the button item "Settings" down
Here is my code
UIBarButtonItem *settingsItem = [[UIBarButtonItem alloc] initWithTitle:#"Settings" style:UIBarButtonItemStylePlain target:self action:nil];
self.navItem.rightBarButtonItem = settingsItem;
[[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0,-10) forBarMetrics:UIBarMetricsDefault];
I had tried it again and again. It seemed that it's not work
Could anyone suggest me how to move the button item "Settings" down ?
You can easily add a Custom Button to your NavigationBarItem, Here is the way,
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; //create custom Button
[button setTitle:#"Settings" forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont systemFontOfSize:14.0]];
[button setTitleColor:[UIColor colorWithRed:179.0/255.0 green:40.0/255.0 blue:18.0/255.0 alpha:1] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 50, 20); //Button frame
[button addTarget:self action:#selector(yourCustomSelectorHere) forControlEvents:UIControlEventTouchUpInside]; //Add action method to the button here
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:button];
UIBarButtonItem *barBtnItem = [[UIBarButtonItem alloc]initWithCustomView: backButtonView]; //set button as UIBarButtonItem
self.navigationItem.rightBarButtonItem = barBtnItem; //set barBtnItem to rightBarButtonItem
By changing backButtonView.bounds values you can change the origin of the Button
Cited from apple's documentation on UIAppearance protocol
iOS applies appearance changes when a view enters a window, it doesn’t
change the appearance of a view that’s already in a window.
So if your code of setting UIBarButtonItem's appearance is after the navigationItem assignment code. It won't work
I'm creating a custom view, which needs to be clickable, hence the button, and need to be in the left at the navigation bar (so, I replace the leftBarButtonItem).
If I add my custom view, to a UIBarButtonItem with - (id)initWithCustomView:(UIView *)customView;, the placement is exactly what I want, but I can't "click" on it. If I add my custom view as an UIButton subView, and use the button in the UIBarButtonItem - (id)initWithCustomView:(UIView *)customView; I can click on it, but now my cusotm view has a topmargin of aproximately 26 points, exceeding the navigationBar height.
This has the correct position, but can't click on it
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 44)];
....
UIBarButtonItem *customButton = [[UIBarButtonItem alloc] initWithCustomView:customView];
self.navigationItem.leftBarButtonItem = customButton;
This has the wrong position, but can click on it
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 44)];
....
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addSubview:customView];
[button addTarget:self action:#selector(userProfile) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *customButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self.navigationItem.leftBarButtonItem = customButton;
Hope I have made myself clear. I'm really clueless with this. I've tried forcing imageEdgeInsets in the UIButton, modifying the frame "y" origin making it negative... but nothing works.
EDIT: #kschaeffer solution works. Just needed to set the button frame the same as the customView frame.
This no longer works in iOs 7
In this case, it gets an unwanted left margin, and stops being clickable (no touch event gets recorded for the button as far as I see)
Try to set the customButton frame the same as the custom view. This actually works for me.
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 44)];
UIButton *customButton = [[UIButton alloc] initWithFrame:customView.bounds];
[customButton addTarget:target action:#selector(userProfile) forControlEvents:UIControlEventTouchUpInside];
[customView addSubview:customButton];
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithCustomView:customView];
self.navigationItem.rightBarButtonItem = customItem;
I create left Bar button item with next method:
- (void)leftButtonOnNavigationItem:(NSString *)imageName type:(NSInteger)type
{
UIImage *backImg = [UIImage imageNamed:imageName];
UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(0.f, 0.f, backImg.size.width, backImg.size.height)];
if (type == 0)
[backBtn addTarget:self.navigationController action:#selector(pop) forControlEvents:UIControlEventTouchUpInside];
else
[backBtn addTarget:self action:#selector(leftMake) forControlEvents:UIControlEventTouchUpInside];
backBtn.contentMode = UIViewContentModeCenter;
[backBtn setImage:backImg forState:UIControlStateNormal];
UIView *backBtnView = [[UIView alloc] initWithFrame:backBtn.bounds];
backBtnView.bounds = CGRectOffset(backBtnView.bounds, -6, 0);
[backBtnView addSubview:backBtn];
UIBarButtonItem *backBarBtn = [[UIBarButtonItem alloc] initWithCustomView:backBtnView];
self.navigationItem.leftBarButtonItem = backBarBtn;
}
I need add button on View because when I use CGRectOffset for button it is not work. So with this case my button on one od the UIViewController shown
So it is what I want. But UIBarButton began clicked only on UIBarButton (area of the rectangle). But when I add only button in UIBarButtonItem it is work even if I clicked on area of UINavigationBar that you can see on screen.
I add button like this:
- (void)leftButtonOnNavigationItem:(NSString *)imageName type:(NSInteger)type
{
UIImage *backImg = [UIImage imageNamed:imageName];
UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(0.f, 0.f, backImg.size.width, backImg.size.height)];
if (type == 0)
[backBtn addTarget:self.navigationController action:#selector(pop) forControlEvents:UIControlEventTouchUpInside];
else
[backBtn addTarget:self action:#selector(leftMake) forControlEvents:UIControlEventTouchUpInside];
backBtn.contentMode = UIViewContentModeCenter;
[backBtn setImage:backImg forState:UIControlStateNormal];
// UIView *backBtnView = [[UIView alloc] initWithFrame:backBtn.bounds];
// backBtnView.bounds = CGRectOffset(backBtnView.bounds, -6, 0);
// [backBtnView addSubview:backBtn];
UIBarButtonItem *backBarBtn = [[UIBarButtonItem alloc] initWithCustomView:backBtn];//View];
self.navigationItem.leftBarButtonItem = backBarBtn;
}
and now my button shown like this
So CGRectOffset not work and my UIBarButton very close to left side of screen, but it is work fine by tap all area on navigation bar, that you see on screen. So I can touch in all area on navigation Bar and UIBarButton will work fine
So I need: UIBarButton must shown like in first case with more area from left side. But it must work by click not only button but all surround ares like in second case. What I must do?
EDIT
In first case button clicked if i tap next area
In second case button clicked if i tap next area
I need position of button like in first case (more origin.x from left side) but clickable area like in second case
All controls/elements that can be interacted with inherit from UIView. UIView provides a method called - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
It is possible to reimplement this method in your own subclass to increase or decrease the valid hit region of the view (or button in your case). For example, to grow the hit region by 5 points in all directions
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
return CGRectContainsPoint( CGRectInset( self.bounds, -5, -5 ), point );
}
Note the negative values when using CGRectInset(). This is because the function is designed for shrinking a CGRect, so by specifying a negative value, the function will expand the CGRect.
Hope this helps!
You can use UIEdgeInsetsMake. It work for me.
UIImage *buttnImage=[UIImage imageNamed:imageName];
UIButton *backButton=[UIButton buttonWithType:UIButtonTypeCustom];
[backButton setImage:buttnImage forState:UIControlStateNormal];
backButton.frame=CGRectMake(0, 0, (buttnImage.size.width+leftMargin+rightMargin), (buttnImage.size.height+topMargin+bottomMargin));
[backButton setImageEdgeInsets:UIEdgeInsetsMake(topMargin, leftMargin, bottomMargin, rightMargin)];
UIBarButtonItem *backBtn=[[UIBarButtonItem alloc]initWithCustomView:backButton];
self.navigationItem.leftBarButtonItems=#[backBtn];
A view's frame is the size and position of the view within a superview (its parent). So when you go to set backBtnView initWithFrame try:
UIView *backBtnView = [[UIView alloc]
initWithFrame:CGRectOffset(backBtn.frame, -6.0, 0.0)];
and forget about bounds all together, I think that will put you in the right direction.
I fixed it in used accessibility frame.
Just set accessibility frame for button with increased height and width and it will work.
I want to have a uibarbuttonitem in right of back button in navigation bar ( if it is not wrong with apples guide line). I use this code:
UIBarButtonItem listButton = new UIBarButtonItem ("List View",UIBarButtonItemStyle.Bordered ,null);
//assigning left bar buttons
this.NavigationItem .LeftBarButtonItems =
new UIBarButtonItem[] { this.NavigationItem .BackBarButtonItem ,listButton } ;
But this.NavigationItem .BackBarButtonItem always is null. What solution is right for this purpose?
This is the correct implement the same :
UIButton *leftButtonIcon = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, width, height)];
[leftButtonIcon setImage:[UIImage imageNamed:#"yourButtonImageName.png"] forState:UIControlStateNormal];
[leftButtonIcon addTarget:self.viewDeckController action:#selector(YourSelectorMethod) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *leftbtn = [[UIBarButtonItem alloc] initWithCustomView:leftButtonIcon];
[self.navigationItem setLeftBarButtonItem:leftbtn];