2 UIBarButtonItem's using the same custom view only added once - ios

I want to add a thin line between items in my UIToolBar so I'm creating a UIBarButtonItem with a custom view like so:
UILabel *separatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 44)];
separatorLabel.backgroundColor = [UIColor colorWithRGB:0xe5edec];
UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithCustomView:separatorLabel];
Then I add my separator to the items array:
[items addObjectsFromArray:[NSMutableArray arrayWithObjects:someButton1, separator, somebutton2, separator, someButton3, nil]];
I thought this would add 2 separators to my toolbar but it only adds the one at the end. Why is this?
I can fix this by creating 2 duplicate labels and UIBarButtonItem's, but is there any other better way?

Any given instance of UIView can only appear in once in the view hierarchy. If you think about the APIs defined on UIView, this is fairly obvious. For example, UIView has a frame property which defines it's location in the superview. The frame property wouldn't make sense if the viewed appeared in two places.
So you need multiple instances. You can streamline your code by defining a method that creates separators:
- (UILabel *)newSeparator
{
UILabel *separatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 44)];
separatorLabel.backgroundColor = [UIColor colorWithRGB:0xe5edec];
UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithCustomView:separatorLabel];
return separator;
}
And then you can add your items like this:
[items addObjectsFromArray:#[button1, [self newSeparator], button2, [self newSeparator]];
Also, you don't need to use UILabel if you're only displaying a background color. You can just use UIView.

Yes,you just created only one UIBarButtonItem object,so it showed one.
I think the better way is creating a UIBarButtonItem subclass with custom label,then create two objects of the subclass.
I hope my answer can help you.

Related

How to place UILabel in the center of navigation bar

How to place UILabel in the center of navigation bar in XCode 6? Is it possible at all? I can place here, for example, UIButton, but unable to place UILabel. If no, what can I do then? Place a UIButton with the appropriate text and make it non-clickable?
Thanks in advance.
In Xcode 6 if you want to put a label inside the UINavigationBar firstly you have to put a UIView there then put the UILabel inside the UIView (this is from the Storyboard btw).
If you do not put the UIView first then the UILabel will never get put onto the UINavigationBar.
Create a UIView and add UILabel as it's subview and then set your NavigationItem's titleView as previously created UIView.
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 40)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 40)];
label.text = #"Hello";
label.textAlignment = NSTextAlignmentCenter;
[view addSubview:label];
self.navigationItem.titleView = view;
Note: Don't forget to set your own frame values to get better result.
Just make sure you try viewWillLayoutSubviews method instead of viewDidLoad that was what worked for me. Cheers!

Adding updating elements such as a level number and coin total to a navigation bar?

I have managed to change the navigation bar to a custom stretch image and turn the back button a different colour. I'm having trouble setting a level number and coin total in the navigation bar.
I figure there has to be any easier way then messing about with progress HUD's and such - which is all I have seen mention from my research.
I'm trying to achieve a similar look to that attached below - element wise not graphically.
Thank you for any help in advance.
Two solutions:
Make the entire navigation bar into a custom view with your own elements, then update them as needed. Do this using the titleView property of UINavigationItem.
Use the leftBarButtonItem, titleView, and rightBarButtonItem with your own custom views.
I prefer the second method because it is more scalable (visually) - that is your view controller will layout correctly in landscape mode, or on an iPad, or in an oddly sized popover, etc. The left item will align to the left, the right to the right and the middle one in the middle. However, it's a bit more complicated because the left and right items need to be of type UIBarButtonItem. We can get around that like this:
// Set up the red star thing in the middle with a number 6 on it
MyRedStarView* redStarView = [MyRedStarView redStarViewWithValue:6];
self.navigationItem.titleView = redStarView;
// Set up the 'word' button on the left
MyWordButton* wordButton = [MyWordButton defaultWordButton];
UIView* buttonHolderView = [[UIView alloc] initWithFrame:CGRectZero];
buttonHolderView.backgroundColor = [UIColor clearColor];
[buttonHolderView addSubview:wordButton];
buttonHolderView.frame = wordButton.frame;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:buttonHolderView];
// Set up the coin indicator on the right
MyCoinView* coinView = [MyCoinView coinViewWithValue:515];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:coinView];
Notice how I wrapped the button (on the leftBarButtonItem) in a holder view - this is only necessary if you want to do some kind of view transitions on the button. For example if it changes in different contexts and you want to animate the transition by removing the button from the holder view and adding a different one (with a view transition). On the right bar button item I didn't do this, just to show the different approaches.
Of course I used some fake view types to demonstrate - you'd actually have your own references to these so that you can set the property values and update the display of the numbers.
try the following code assuming you already have the navigationView in place
- (void)viewDidLoad
{
// Custom Navigation Bar
// -----------------------------------
UIView *navigationCustomTitle = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 20.0)];
navigationCustomTitle.backgroundColor = [UIColor clearColor];
UIImageView *icon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon.png"]];
UILabel *titleCustomLabel = [[UILabel alloc] initWithFrame:CGRectMake(30.0, 0.0, 260.0, 20.0)];
titleCustomLabel.text = #"A nice title";
titleCustomLabel.textColor = [UIColor whiteColor];
titleCustomLabel.backgroundColor = [UIColor clearColor];
titleCustomLabel.font = [UIFont fontWithName:#"HelveticaNeue-CondensedBold" size:(16.0)];
[navigationCustomTitle addSubview:titleCustomLabel];
[navigationCustomTitle addSubview:icon];
self.navigationItem.titleView = navigationCustomTitle;
}

Show/Hiding a UIBarButtonItem, located in the middle of a UIToolbar

I've read a couple similar questions regarding this topic on StackOverflow, but none of them apply to my case.
I have a UIToolbar on my application. The ToolBar has a layout like the following.
(Button #1) (Button #2) (Button #3) <--- Flex Controller ---> (Button #4)
What is the most efficient way to Show/Hide the Button #3 UIBarButtonItem since it is in the middle of the UIToolbar?
FOLLOW-UP
I am aware of the setItems:Animated method, but this seems like it could be problematic because all of my buttons are wired through IB and they have associated IBActions.
Does this mean that I, therefore, need to find a way to retain my Button #3 when it is hidden (since I am using ARC?) I'm looking for the most optimal/efficient method for adding and removing these objects. If I must recreate this list each time I have to show/hide my #3 button, that's what I will do.
It just seems so inefficient.
Looking in UIToolBar.h, there's the following method:
- (void)setItems:(NSArray *)items animated:(BOOL)animated; // will fade in or out or reorder and adjust spacing
You should just be able to do something like:
NSMutableArray *items = [toolBar.items mutableCopy];
[items removeObjectAtIndex:2];
[toolBar setItems:items animated:YES];
See if that works the way you're looking for
I would recommend building a helper function in the following manner:
- (void) setToolbarItems:(BOOL) button3Shown {
NSMutableArray *items = [NSMutableArray arrayWithCapacity:5];
[items addObject:button1];
[items addObject:button2];
if(button3Shown) {
[items addObject:button3];
}
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
[items addObject:button4];
[self.toolbar setItems:[items copy] animated:YES];
}
This then has the benefit of being available whenever you need to update it and then you can easily add/remove the button. In order for this to work, you would need to have the buttons available in your implementation file as IBOutlets and they would be easily referenced for rebuilding the toolbar.
You need to reset the toolbar items, passing in a new array without the button you want to hide. See Hide UIToolbar UIBarButtonItems for exact details.
Creating different arrays of UIBarButtonItems and adding/removing to/from the UIToolbar at runtime may increase the complexity of execution.
I've done it using a different approach. Here are the snippets for achieving it.
Step 1 : Either create an IBOutlet or Create the UIToolbar instance.
UIToolbar *toolBar = [UIToolbar alloc] init];
Set the required styles if you want.
Step 2 : Create UIButton type instances.
UIButton *button1, *button2;
Step 3: Assign images (if required) to the buttons.
button1 = [UIButton alloc] initWithFrame:CGRectMake(0.f,0.f,30.f,30.f);
[button1 setBackgroundImage:[UIImage imageNamed:#"image1.png"] forState:UIControlStateNormal];
button2 = [UIButton alloc] initWithFrame:CGRectMake(0.f,0.f,30.f,30.f);
[button2 setBackgroundImage:[UIImage imageNamed:#"image2.png"] forState:UIControlStateNormal];
Step 4: Create UIBarButtonItem instances with above buttons as custom view.
UIBarButtonItem *toolbarbuttonItem1 = [UIBarButtonItem alloc] initWithCustomView:button1];
UIBarButtonItem *toolbarbuttonItem2 = [UIBarButtonItem alloc] initWithCustomView:button1];
Step 5: Assign the bar button items to the toolbar.
toolBar.items = [NSArray arrayWithObjects:toolbarbuttonItem1,toolbarbuttonItem2,nil];
Step 6: Add the Toolbar to the VIEW.
Step 7: Create a UIButton IBOutlet in the VIEW and assign a click event.
Invoke the following helper method int the click event to toggle hiding.
- (void) toggleToolbarButtons {
button1.hidden = !button1.hidden;
button2.hidden = !button2.hidden;
}
Hope that helps!!
With existing references to toolbar items item1, item2 and item3, the most straightforward way is to remove all items and then re-add each item in the order you want it. This code is written from the perspective of being within a UIToolbar subclass:
let flexSpace: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let fixedSpace: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
self.items?.removeAll()
self.items?.append(flexSpace)
self.items?.append(item1)
self.items?.append(fixedSpace)
self.items?.append(item3)
self.items?.append(fixedSpace)
self.items?.append(item2)
These item references can be from IBOutlets. Change these references to be strong rather than the IB-inserted-default weak references, so that the UIToolbar will maintain references to these items even when they have been removed, thus maintaining the relevant IBAction function relationships.
To remove a specific item from your UIToolbar from within a UIToolbar subclass, without having to re-set all items:
if let index = self.items?.index(of: buttonToRemove) {
self.items?.remove(at: index)
}
If not within a UIToolbar subclass, simply replace self with a reference to the UIToolbar throughout.

Separator between toolbar items in UIToolbar

How to add a separator between buttons in a UIToolbar?
Sample image is shown in the below link
I did it with a custom view button, with a 1 pixel wide background:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 44)];
label.backgroundColor = [UIColor whiteColor];
UIBarButtonItem *divider = [[UIBarButtonItem alloc] initWithCustomView:label];
// Add button to array of toolbar items
[items addObject:divider];
// Or set items directly:
//toolbar.items = [NSArray arrayWithObject:divider];
label.text = #"";
I can think of two ways :
(a) You could make them very thin toolbar buttons with user interaction disabled.
(b) Your other choice would be to implement your own toolbar. I'd try (a) first ;)
You can also make a toolbar button and set the Title = |
If yo want a clean, simple layout I would prefer a very thin image with this separator in it. Then you can add fix distances between your normal button, the separator image button (user interaction disabled) and the next button.

UIToolbar in iPad

I wanted to have two buttons on the both end of Navigation Bar (in iPad's Detail View Controller).
So I created two UIToolbars and I set the them as Left&RightBarButtonItems.
But, There is some color variation in the NavigationBar.
Attached images for your understanding.
the code I used ,
UIToolbar *leftToolbar =[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 200, 45)];
NSMutableArray *lItems = [[NSMutableArray alloc] initWithArray:[leftToolbar items]];
UIBarButtonItem *lb1 =[[UIBarButtonItem alloc]initWithTitle:#"Home"style:UIBarButtonItemStyleBordered target:self action:#selector(home:) ];
UIBarButtonItem *lb2 =[[UIBarButtonItem alloc]initWithTitle:#"New Document"style:UIBarButtonItemStyleBordered target:self action:#selector(newDoc:) ];
[lItems insertObject:lb1 atIndex:0];
[lItems insertObject:lb2 atIndex:1];
[leftToolbar setItems:lItems animated:YES];
[lItems release];
leftToolbar.barStyle =UIBarStyleBlackTranslucent;
leftToolbar.tintColor=[UIColor clearColor];
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc] initWithCustomView:leftToolbar];
Can you help me to avoid this color variation?
Is there any other way to have buttons like this, without using UIToolbar?
Thanks ,
Gopi.
just remove navigation bar and add tool bar, why you adding toolbar to navigation bar?
To achieve the same, use segment controll, set it in Left or right barbutton's view, once you select a segmet, deselect it after few seconds, say 0.3secs, it looks good, no color vairations, it looks like a part of Navigation bar
Found the solution !
code is correct, but one small bug. Have to set the height to 44, not 45. I did this and it seems to fit over the existing NavigationBar.
UIToolbar *leftToolbar =[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 200, 44)];
Works for me . . Anyway I moved to the Single tool bar method.
Hope this helps some one.!!
Have a great day!!
Gopi.

Resources