subjective-c
subjective-c

Reputation: 1823

How to change image and disable UIBarButtonItem

I have a NavigationBar app with two views: a parent and a sub view. In the sub view I'm adding a button to the right corner as follows:

- (void)viewDidLoad {
    UIBarButtonItem *tempButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:@selector(lockScreen)];
    self.navigationItem.rightBarButtonItem = tempButton;
    [tempButton release];
}

When that button is clicked I want to change the image of this rightBarButtonItem and disable the leftBarButtonItem (which was added automatically by the controller). Basically have two states of a button, locked and unlocked.

Question 1: The only way I can find how to change the image is to create a new UIButtonItem with a new image and replace rightBarButtonItem with that new one. But I'm wondering if there's a way to just change the image without creating a new UIBarButtonItem. Am I creating a memory leak if I keep creating new UIBarButtonItem?

Question 2: How can I get a hold of self.navigationItem.leftBarButtonItem and disable/enable it? I don't create that one manually, it's created automatically for me by the controller. I don't see any method/property on UIBarButtonItem to enable/disable user interaction with it.

Upvotes: 9

Views: 47281

Answers (7)

eelco
eelco

Reputation: 1607

In regard to question 2, use the 'enabled' property:

 self.navigationItem.leftBarButtonItem.enabled = NO;

Upvotes: 7

Hayden
Hayden

Reputation: 11

Shouldn't the above have release the UILabel *l after the [self.window addSubView:l] call? That way it gets retained +1 when added to the Subview, but released -1 in the same branch. Otherwise, you must call disableLeftBarButtonItemOnNavbar:NO to release it. And while, you'll end up in the same place in the end, you aren't leaking, I think the static analysis tools they've built into XCode wouldn't like that being in a separate branch. Small detail :-)

- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
    static UILabel *l = nil;

    if (disable) {
        if (l != nil)
            return;
        l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
        l.backgroundColor = [UIColor clearColor];
        l.userInteractionEnabled = YES;
        [self.window addSubview:l];
        [l release];
    }
    else {
        if (l == nil)
            return;
        [l removeFromSuperview];
        l = nil;
    }
}

Upvotes: 1

Naveen Shan
Naveen Shan

Reputation: 9192

I think this code helps you,

UIButton *m_objbtnFlip= [[UIButton alloc] initWithFrame:CGRectMake(0,0,89, 37)];
    [m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"btn_purchased"
                                                                                                 ofType:IMAGETYPE]]
                       forState:UIControlStateNormal];
    [m_objbtnFlip setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"btn_allavailable"
                                                                                                 ofType:IMAGETYPE]]
                       forState:UIControlStateSelected];
    [m_objbtnFlip addTarget:self action:@selector(flipViews) forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *objBarButtonItemRight = [[UIBarButtonItem alloc] initWithCustomView:m_objbtnFlip];

    self.navigationItem.rightBarButtonItem=objBarButtonItemRight;
    [objBarButtonItemRight release];
    objBarButtonItemRight = nil;

And write action here,

-(void)flipViews    {
   // put action code here
}

Upvotes: 0

Ahmet Ardal
Ahmet Ardal

Reputation: 1172

Using "hidesBackButton=YES" is really not an elegant solution, cause it HIDES the button which is not what we want. An acceptable work-around would be adding a UILabel to the window just over the back button at least disabling the touches on the button.

Add this method to your AppDelegate class:

- (void) disableLeftBarButtonItemOnNavbar:(BOOL)disable
{
    static UILabel *l = nil;

    if (disable) {
        if (l != nil)
            return;
        l = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 160, 44)];
        l.backgroundColor = [UIColor clearColor];
        l.userInteractionEnabled = YES;
        [self.window addSubview:l];
    }
    else {
        if (l == nil)
            return;
        [l removeFromSuperview];
        [l release];
        l = nil;
    }
}

You can call it like this from any view controller to disable:

MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:YES];

To enable:

MyAppDelegate *appDeleg = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
[appDeleg disableLeftBarButtonItemOnNavbar:NO];

Upvotes: 0

Rei
Rei

Reputation: 1158

I was not able to disable/grey out a NavBar button with:

self.navigationItem.leftBarButtonItem.enabled = NO;

...but hiding the back button works well!

self.navigationItem.hidesBackButton = YES;

Thanks Dzamir!

Upvotes: 0

Dzamir
Dzamir

Reputation: 145

I can't understand if you have a navigationController, but in this case to disable the back button you need to call:

self.navigationItem.hidesBackButton = YES;

Upvotes: 5

Gcoop
Gcoop

Reputation: 3382

Question 1: Declare UIBarButtonItem *tempButton in the interface

@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
    UIBarButtonItem *tempButton;
}

@property (nonatomic, retain) UIBarButtonItem *tempButton;

and synthesize it in the implementation.

@synthesize tempButton;

Create the object in viewDidLoad similiar to how you are now.

- (void)viewDidLoad {
  tempButtom = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"lock-unlocked.png"] style:UIBarButtonItemStylePlain target:self action:@selector(lockScreen)];
  self.navigationItem.rightBarButtonItem = tempButton;
}

But don't release it here, release it in the dealloc method normally found at the bottom.

Then when lockScreen is called do

tempButton.image = [UIImage imageNamed:@"myImage.png"]

I don't have an answer for question 2, im afraid!

Upvotes: 18

Related Questions