Khalid Usman
Khalid Usman

Reputation: 1282

How can i change the style of UIBarButtonItem in code

I am using UIBarButtonSystemItemPlay to play my audio file and i want to change it's style dynamically when i click it. Is it possible?, if yes, then please help me. This is my code, where _playPause is IBOutlet of UIBarButtonSystemItemPlay. Thanks in advance.

- (IBAction)playPause:(UIBarButtonItem *) sender
{
    if (_playPause.style == UIBarButtonSystemItemPlay)
    {
        [_playPause setStyle:UIBarButtonSystemItemPause];
        [audio play];
    }
    else
    {
        [_playPause setStyle:UIBarButtonSystemItemPlay];
        [audio pause];
    }
}

Upvotes: 9

Views: 14522

Answers (4)

William Entriken
William Entriken

Reputation: 39263

Yes, you can't change the "style" (it's not actually called style) once it is set.

Yes, you can make another button that fixes it.

Here is reusable code that does that:

UIBarButtonItem *newButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
    target:controller.navigationItem.rightBarButtonItem.target
    action:controller.navigationItem.rightBarButtonItem.action];
controller.navigationItem.rightBarButtonItem = newButton;

Here, controller is usually self.

Upvotes: 0

mowliv
mowliv

Reputation: 135

Here's a pretty complete solution for this that I just implemented:

First, define vars to hold both buttons:

@property (weak, nonatomic) IBOutlet UIToolbar *toolbar;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *playButton;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *pauseButton;

(My understanding here is that the toolbar is a weak ref since it is being defined via IB and it has a strong pointer to it, but that the play/pause buttons are strong pointers because we are creating them below. But my fu is a little weak on this front as a fairly newbie, so corrections appreciated.)

Second, in IB create just a play button (no pause button) and tie it to the above playButton var.

Third, set up this method:

- (void) setAsPlaying:(BOOL)isPlaying
{
    self.rootViewController.playing = isPlaying;

    // we need to change which of play/pause buttons are showing, if the one to
    // reverse current action isn't showing
    if ((isPlaying && !self.pauseButton) || (!isPlaying && !self.playButton))
    {
        UIBarButtonItem *buttonToRemove = nil;
        UIBarButtonItem *buttonToAdd = nil;
        if (isPlaying)
        {
            buttonToRemove = self.playButton;
            self.playButton = nil;
            self.pauseButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPause
                                                                             target:self
                                                                             action:@selector(pauseAudio:)];
            buttonToAdd = self.pauseButton;
        }
        else
        {
            buttonToRemove = self.pauseButton;
            self.pauseButton = nil;
            self.playButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay
                                                                            target:self
                                                                            action:@selector(playAudio:)];
            buttonToAdd = self.playButton;
        }

        // Get the reference to the current toolbar buttons
        NSMutableArray *toolbarButtons = [[self.toolbar items] mutableCopy];

        // Remove a button from the toolbar and add the other one
        if (buttonToRemove)
            [toolbarButtons removeObject:buttonToRemove];
        if (![toolbarButtons containsObject:buttonToAdd])
            [toolbarButtons insertObject:buttonToAdd atIndex:2];    // vary this index to put in diff spots in toolbar

        [self.toolbar setItems:toolbarButtons];
    }
}

Fourth, call setAsPlaying wherever you are going to play or pause mode. For instance:

-(IBAction) playAudio:(id)sender
{
    [self.audioPlayer play];
    [self setAsPlaying:YES];
}

-(IBAction) pauseAudio:(id)sender
{
    [self.audioPlayer pause];
    [self setAsPlaying:NO];
}

Upvotes: 2

Lorenzo B
Lorenzo B

Reputation: 33428

UIBarButtonSystemItemPlay or UIBarButtonSystemItemPause cannot be retrieved by style property. style is of type UIBarButtonItemStyle.

Check the documentation here.

I suggest to create two different UIBarButtonItem and then enable or disable (for example) them alternately. It is also possible to remove the current visible button and add a new one with a different UIBarButtonSystemItem.

Upvotes: 5

user843337
user843337

Reputation:

I believe that once the style is set initially (i.e. in interface builder or when you create the button in code) you can't change it.

Your only other option is to remove the button in code and create a new one in its place using a different style. You could call this method:

- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action

For more info on the UIBarButtonItem take a look at this.

Upvotes: 0

Related Questions