views:

1963

answers:

4

All of the examples I've seen on here and other sites involved creating a UIActivityIndicatorView and loading it with something like:

self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] 
          initWithCustomView:myActivityIndicatorView 
          target:nil 
          action:nil] 
         autorelease];

However, that just creates a plain activity indicator in the navigation bar. What I want to do is have a button that looks just like the normal UIBarButtonSystemItem buttons but with an activity indicator instead of one of the default images. I've tried doing initWithImage and initWithTitle with nil images or titles and then adding the activity indicator as a subview, but that doesn't work.

Any ideas?

+1  A: 

have you tried creating a UIButton in the button bar and then adding an activity indicator as a subView of the UIButton?

Roger Nolan
I tried that but I couldn't seem to get it to work.
Jarin Udom
A: 

I have this working and it is very simple. Just place the activity indicator where you want it with IB, but make sure it's lower in the list than the bar you want it on, and is at the "top level" (not a subview of anything else). Then control it in code via an outlet.

Steve Weller
+1  A: 

Here's something that can help:

activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[activityIndicator startAnimating];
UIBarButtonItem *activityItem = [[UIBarButtonItem alloc] initWithCustomView:activityIndicator];
[activityIndicator release];
self.navigationItem.rightBarButtonItem = activityItem;
[activityItem release];
[activityIndicator startAnimating];
Carlos
+2  A: 

My Solution is to create a subclass of UIButton:

in SOActivityButton.h:

@interface SOActivityButton : UIButton 
{
UIActivityIndicatorView* activityIndicator;
}
@end

in SOActivityButton.m:

@implementation SOActivityButton

- (id)initWithFrame:(CGRect)frame 
{
    if (self = [super initWithFrame:frame]) 
    {
        CGRect innerFrame = CGRectInset(frame, 8.0f, 8.0f);
        activityIndicator = [[UIActivityIndicatorView alloc]
                                    initWithFrame:innerFrame];
        activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
        [self addSubview:activityIndicator];
    }
    return self;
}

- (void)dealloc 
{
    [activityIndicator release], activityIndicator = nil;
    [super dealloc];
}

- (void) startAnimating
{   
    [activityIndicator startAnimating];
}

- (void) stopAnimating
{   
    [activityIndicator stopAnimating];
}
@end

Then to use it:

SOActivityButton* activityButton = [[SOActivityButton alloc] 
                    initWithFrame:CGRectMake(0.0f, 0.0f, 32.0f, 32.0f)];
[activityButton setImage:[UIImage imageNamed:@"button-background.png"]
                    forState:UIControlStateNormal];
[activityButton addTarget:self action:@selector(myAction:) 
                    forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *activityBarButtonItem = [[UIBarButtonItem alloc] 
                    initWithCustomView:activityButton];
[activityButton release];
self.navigationItem.rightBarButtonItem = activityBarButtonItem;
[activityBarButtonItem release];

You will need to find or create a button-background.png. The PSD here should have one.

Alan Rogers
Hum, a UIBarButtonItem is not a UIButton, so your "subclass" approach should be more applied to a UIBarButtonItem directly in that case.
yonel
Not really, as UIBarButtonItem doesn't give you easy access to it's View hierarchy. You are still going to have to create your own Views to replace UIBarButtonItem's customView, there is not much point subclassing UIBarButtonItem to do that.
Alan Rogers
This rocks a shame it hasn't been accepted as an answer. Thanks
Nick