Uibarbuttonitem Custom View in Uinavigationbar

UIBarButtonItem Custom view in UINavigationBar

From Apple documentation:

Initializes a new item using the specified custom view.

- (id)initWithCustomView:(UIView *)customView

Parameters
customView
A custom view representing the item.
Return Value
Newly initialized item with the specified properties.

Discussion:
The bar button item created by this method does not call the action method of its target in response to user interactions. Instead, the bar button item expects the specified custom view to handle any user interactions and provide an appropriate response.

Solution: "Create button with your background image (set action to this button) and init bar button with this button". For example:

UIButton *btn =  [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0,0,25,25)
[btn setBackgroundImage:[UIImage imageNamed:@"chk_back.png"] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(BackBtn) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc] initWithCustomView:btn];

Placing a custom view based UIBarButtonItem in the navigation bar without default horizontal padding

55As commented above, the solution I went with is based on this answer to a different, but very much related question: How to adjust UIToolBar left and right padding. It is also facilitated by (and depends on) iOS5, which allows you to set multiple buttons on the left or right side, instead of just one.

Here's an example of removing the padding to the left of a custom left button item:

UIBarButtonItem *backButtonItem // Assume this exists, filled with our custom view

// Create a negative spacer to go to the left of our custom back button,
// and pull it right to the edge:
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = -5;
// Note: We use 5 above b/c that's how many pixels of padding iOS seems to add

// Add the two buttons together on the left:
self.navigationItem.leftBarButtonItems = [NSArray
arrayWithObjects:negativeSpacer, backButtonItem, nil];

And with this, the left padding for the left bar button item in a navigation bar, is gone!

NOTE: This has worked for me in iOS5 and iOS6. Given that iOS7 is considerably different (from the public demos), those of you with the early seeds of iOS7 should test if something so unintentional, like this hack, will actually continue to work for you beyond iOS6.

How to add custom view on right of navigation bar Swift?

// creating uiview and add three custom buttons

 func addRightButton(){

let viewFN = UIView(frame: CGRectMake(0, 0, 180,40))
viewFN.backgroundColor = UIColor.yellowColor()
let button1 = UIButton(frame: CGRectMake(0,8, 40, 20))
button1.setImage(UIImage(named: "notification"), forState: UIControlState.Normal)
button1.setTitle("one", forState: .Normal)

button1.addTarget(self, action: #selector(self.didTapOnRightButton), forControlEvents: UIControlEvents.TouchUpInside)

let button2 = UIButton(frame: CGRectMake(40, 8, 60, 20))
button2.setImage(UIImage(named: "notification"), forState: UIControlState.Normal)
button2.setTitle("tow", forState: .Normal)
let button3 = UIButton(frame: CGRectMake(80, 8, 60, 20))
button3.setImage(UIImage(named: "notification"), forState: UIControlState.Normal)
button3.setTitle("three", forState: .Normal)

button3.addTarget(self, action: #selector(self.didTapOnRightButton), forControlEvents: UIControlEvents.TouchUpInside)

viewFN.addSubview(button1)
viewFN.addSubview(button2)
viewFN.addSubview(button3)

let rightBarButton = UIBarButtonItem(customView: viewFN)
self.navigationItem.rightBarButtonItem = rightBarButton

}

Adding a custom UIBarButtonItem to a UINavigationBar

does work for me. i just got rid of target action so i don't have to implement it. all done in code. no storyboards and no xibs.

AppDelegate.swift

var window: UIWindow?
let viewController = ViewController();

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

let navigationController = UINavigationController(rootViewController:viewController)

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()

return true
}

ViewController.swift

override func viewDidLoad() {
super.viewDidLoad()

let button = UIButton(type: .Custom)
button.setTitle("+", forState: .Normal)
button.titleLabel?.font = UIFont.systemFontOfSize(20.0)
button.frame = CGRectMake(0, 0, 100, 40)

self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "+", style: .Plain, target: self, action: nil)
self.navigationItem.rightBarButtonItem?.setTitleTextAttributes([NSFontAttributeName:UIFont.systemFontOfSize(40)], forState: .Normal)

}

customView on left button of UINavigationBar

Yes, your UIButton doesn't come with any shading. What I've done is used a UISegmentedControl to get shading for free:

// Add the Menu button to the navigation bar
NSString* menuLabel = "ShadeButton";
CGSize textSize = [menuLabel sizeWithFont:[UIFont systemFontOfSize:15.0]];
UISegmentedControl* menuSegmentedButton = [[UISegmentedControl alloc]
initWithFrame:CGRectMake(0.0f, 0.0f, textSize.width, 29.0f)];
menuSegmentedButton.momentary = YES;
menuSegmentedButton.selected = NO;
menuSegmentedButton.segmentedControlStyle = UISegmentedControlStyleBar;
[menuSegmentedButton insertSegmentWithTitle:menuLabel atIndex:0
animated:NO];
[menuSegmentedButton addTarget:self action:@selector(doMenu)
forControlEvents:UIControlEventValueChanged];
UIBarButtonItem* barButton = [[UIBarButtonItem alloc]
initWithCustomView:menuSegmentedButton];
[menuSegmentedButton release];
self.navigationItem.rightBarButtonItem = barButton;

Create your UIBarButtonItem with the UISegmentedControl as shown above rather than a UIButton and you should get the effect you're after. The alternative is to do more work on the button and create a texture/custom image for it yourself.

UIBarButtonItem with UIButton as CustomView - from UIButton, how to access the UIBarButtonItem its in?

If you have set your UIButton as the customView of a UIBarButtonItem, or a child of the custom view, then you can walk up the view hierarchy from your button until you find the UIToolbar or UINavigationBar that contains the button, then search the bar's items for the one whose custom view is the button (or an ancestor of the button).

Here's my completely untested code for doing that. You would call [[self class] barButtonItemForView:myButton] to get the item containing your button.

+ (BOOL)ifBarButtonItem:(UIBarButtonItem *)item containsView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
UIView *customView = item.customView;
if (customView && [view isDescendantOfView:customView]) {
*outItem = item;
return YES;
} else {
return NO;
}
}

+ (BOOL)searchBarButtonItems:(NSArray *)items forView:(UIView *)view storeItem:(UIBarButtonItem **)outItem {
for (UIBarButtonItem *item in items) {
if ([self ifBarButtonItem:item containsView:view storeItem:outItem])
return YES;
}
return NO;
}

+ (UIBarButtonItem *)barButtonItemForView:(UIView *)view {
id bar = view;
while (bar && !([bar isKindOfClass:[UIToolbar class]] || [bar isKindOfClass:[UINavigationBar class]])) {
bar = [bar superview];
}
if (!bar)
return nil;

UIBarButtonItem *item = nil;

if ([bar isKindOfClass:[UIToolbar class]]) {
[self searchBarButtonItems:[bar items] forView:view storeItem:&item];
}

else {
UINavigationItem *navItem = [bar topItem];
if (!navItem)
return nil;
[self ifBarButtonItem:navItem.backBarButtonItem containsView:view storeItem:&item]
|| [self ifBarButtonItem:navItem.leftBarButtonItem containsView:view storeItem:&item]
|| [self ifBarButtonItem:navItem.rightBarButtonItem containsView:view storeItem:&item]
|| ([navItem respondsToSelector:@selector(leftBarButtonItems)]
&& [self searchBarButtonItems:[(id)navItem leftBarButtonItems] forView:view storeItem:&item])
|| ([navItem respondsToSelector:@selector(rightBarButtonItems)]
&& [self searchBarButtonItems:[(id)navItem rightBarButtonItems] forView:view storeItem:&item]);
}

return item;
}

UIBarButtonItem with custom view not properly aligned on iOS 7 when used as left or right navigation bar items

In order to fix this bug, you must subclass UIButton so that you can override alignmentRectInsets. From my testing, you'll need to return a UIEdgeInsets with either a positive right offset or a positive left offset, depending on the button position. These numbers make no sense to me (at least one of them should be negative, according to common sense), but this is what actually works:

- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (IF_ITS_A_LEFT_BUTTON) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF_ITS_A_RIGHT_BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}

Special thanks to @zev for suggesting I try adjusting alignmentRectInsets.



Related Topics



Leave a reply



Submit