2

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.

RLH
  • 15,230
  • 22
  • 98
  • 182
  • probably you've tried it already, but can't you just use `hidden` property of the button? – Novarg Mar 06 '12 at 16:38
  • @Novarg: That property isn't available on the UIBarButtonItem because it isn't inherited from UIButton. – RLH Mar 06 '12 at 16:41
  • Wire the buttons as IBOutlets and then you can reference them when adjusting the toolbar's items. I've put in an answer which describes the method I use when doing this to simplify matters. – Chad Mar 06 '12 at 16:59

5 Answers5

5

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

Ash Furrow
  • 12,391
  • 3
  • 57
  • 92
  • 1
    Now, how would I add back in the item that was removed, once it should be shown? FYI, the button is wired in through IB and has an associated IBAction. – RLH Mar 06 '12 at 16:49
  • You'd have to store the `UIBarButtonItem` in an instance variable and go through a similar procedure to add it back in later. Being from IB shouldn't affect anything. – Ash Furrow Mar 06 '12 at 16:58
4

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.

Chad
  • 890
  • 6
  • 20
  • just a note, this is a great solution, but `UIBarButtonItem`s created with the `initWithCustomView:` method will also need to have their frames set. – oflannabhra Oct 19 '15 at 13:05
0

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!!

Raghu
  • 1
  • 2
0

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.

Duncan Babbage
  • 19,972
  • 4
  • 56
  • 93
0

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.

Community
  • 1
  • 1
Jim
  • 2,300
  • 1
  • 19
  • 43