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.
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!
In regard to question 2, use the 'enabled' property:
self.navigationItem.leftBarButtonItem.enabled = NO;
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;
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;
}
}
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!
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];
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
}
Related
I want to set custom back bar button for all controllers in the app. I tried using this:
[[UIBarButtonItem appearance]
setBackButtonBackgroundImage:backButtonImage
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
It sets the image. That's OK. But, what i really want to do is that, i just want a custom button for back bar button which does not contain any title etc. The code above works, but it adds automated titles and resizes the back bar button item. My need is to have a fixed frame, no-title back bar button item for all controllers in the app.
I've resolved it. Just make a category over UIViewController and import it in prefix.pch file. Then write a method: customViewWillAppear: and swizzle it with viewWillAppear method:
+(void)load{
Method viewWillAppear = class_getInstanceMethod(self, #selector(customViewWillAppear:));
Method customViewWillAppear = class_getInstanceMethod(self, #selector(viewWillAppear:));
method_exchangeImplementations(viewWillAppear, customViewWillAppear);
}
Add the above method to that category class. Then implement your customViewWillAppear method like this:
-(void)customViewWillAppear:(BOOL)animated{
[self customViewWillAppear:animated];
if([self.navigationController.viewControllers indexOfObject:self] != 0 && !self.navigationItem.hidesBackButton){
UIBarButtonItem *cancelBarButton = nil;
UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cancelButton addTarget:self action:#selector(popViewControllerWithAnimation) forControlEvents:UIControlEventTouchUpInside];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"yourImage.png"] forState:UIControlStateNormal];
[cancelButton sizeButtonToFit];
cancelBarButton = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];
NSMutableArray * leftButtons = [NSMutableArray arrayWithObject:cancelBarButton];
[leftButtons addObjectsFromArray:self.navigationItem.leftBarButtonItems];
[self.navigationItem setLeftBarButtonItem:nil];
[self.navigationItem setLeftBarButtonItems:leftButtons];
}
[self.navigationItem setHidesBackButton:YES];
}
-(void)popViewControllerWithAnimation{
[self.navigationController popViewControllerAnimated:YES];
}
Now, for every controller in your code, you have a custom back button. This took me a lot of time to implement and figure out. Hope it'll help you guys all too.
EDIT:
Please use the following code to support iOS7> back swipe feature;
UIImage *image = [UIImage imageForName:#"some_image"];
navBar.backIndicatorImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
navBar.backIndicatorTransitionMaskImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
Create a base view controller and add the following code;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
}
I've had a similar problem before and I've searched everywhere for a solution.
The only one I've found, which works for your problem was to implement in EVERY view controller a UILeftBarButton which does the popping.
You can change the background image the way you're doing, but if you set the text to nil or empty text (""), you're button just won't show up.
You also can't change the View of the UIBackBarButton, only it's text (so no custom button).
What i did, was set the backbutton title label alpha to zero, using appearance proxy.
My code in ViewDidLoad:
// Set back button image
if ([[self.navigationController viewControllers] objectAtIndex:0] != self) {
UIButton *btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
btnBack.frame = CGRectMake(0,0,38,30);
[btnBack setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackButton"] forState:UIControlStateNormal];
[btnBack addTarget:self.navigationController action:#selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *leftBtn = [[UIBarButtonItem alloc] initWithCustomView:btnBack];
[self.navigationItem setLeftBarButtonItem:leftBtn];
}
You could write a category like this,
//
// UINavigationItem+BarAditions.h
//
// Created by Satheeshwaran on on 7/5/13.
//
#import <Foundation/Foundation.h>
#interface UINavigationItem (PersonaAddition)
- (void)setCustomBackButton;
#end
//
// UINavigationItem+BarAditions.m
//
// Created by Satheeshwaran on on 7/5/13.
//
#import "UINavigationItem+PersonaAddition.h"
#implementation UINavigationItem (PersonaAddition)
- (void)setCustomBackButton
{
//customize ur back button here.
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame=CGRectMake(0, 0, 60, 30);
[backButton addTarget:target action:#selector(didPressLeftItem:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.leftBarButtonItem = barItem;
}
and import this category in all ur files and call the setCustomBackButton in all ur classes. This works fine for me, even in iOS 7.
In ViewDidLoad of all ur classes.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationItem setCustomBackButton];
}
try this code:
UIButton *tempbtn = [[UIButton alloc] init];
[tempbtn setImage:[UIImage imageNamed:#"testbtn.png"] forState:UIControlStateNormal];
UIBarButtonItem *temp = [[UIBarButtonItem alloc] initWithCustomView:tempbtn];
self.navigationItem.rightBarButtonItem = temp;
I am using UIImagePickerController with a custom overlay to record a video in my app. For the implementation of the UIImagePickerController, I have used the code from a great Ray Wenderlich tutorial.
I have hidden the controls for the camera, and created a simple custom overlay view. This has worked and loads fine.
I have then created a toolbar and buttons for the view, to record the video:
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
usingDelegate: (id <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>) delegate {
if (([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera] == NO)
|| (delegate == nil)
|| (controller == nil))
return NO;
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
// Displays a control that allows the user to choose movie capture
cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
// Hides the controls for moving & scaling pictures, or for
// trimming movies. To instead show the controls, use YES.
cameraUI.allowsEditing = NO;
cameraUI.delegate = delegate;
//Overlay view and toolbar setup
// creating overlayView
UIView* overlayView = [[UIView alloc] initWithFrame:cameraUI.view.frame];
// letting png transparency be
float width = 320;
float AR = (4.0/3.0);
float toolbar_height = 480 - (AR*width);
UIToolbar *toolBar=[[UIToolbar alloc]initWithFrame:CGRectMake(0, (AR*width), 320, toolbar_height)];
//toolBar.tintColor = [UIColor colorWithRed:(252/255.) green:(0/255.) blue:(48/255.) alpha:1];
toolBar.tintColor = [UIColor colorWithRed:(49/255.) green:(52/255.) blue:(49/255.) alpha:1];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *RecordBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(recordPressed:)];
UIBarButtonItem *CancelBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(imagePickerControllerDidCancel:)];
NSArray *buttons = [NSArray arrayWithObjects: CancelBarButtonItem, flexibleSpace, RecordBarButtonItem, flexibleSpace, nil];
[toolBar setItems: buttons animated:NO];
[overlayView addSubview:toolBar];
[overlayView.layer setOpaque:NO];
overlayView.opaque = NO;
cameraUI.showsCameraControls = NO;
cameraUI.cameraOverlayView = overlayView;
[controller presentViewController: cameraUI animated: YES completion:nil];
return YES;
}
My button recordBarButtonItem calls recordPressed which is given by:
- (void) recordPressed: (UIImagePickerController *) picker {
NSLog(#"lets record");
[picker startVideoCapture];
}
So the 'lets record' appears on the log, but I receive an NSInvalidArgumentException error for the startVideoCapture. I know theres something obviously wrong with the way im trying to start the video capture through the button press, but I cant figure it out. Still quite a novice at iOS so forgive me if the solution is simple!
Cheers,
Mike
The problem is that the action you attach to the initWithBarButtonSystemItem call doesn't pass the UIImagePickerController instance along.
What I would do is set the UIImagePickerController as a property of your class and access that property from your action, like this:
In your .h:
#property (nonatomic, strong) UIImagePickerController *cameraUI;
In your .m:
- (BOOL) startCameraControllerFromViewController: (UIViewController*) controller
usingDelegate: (id <UIImagePickerControllerDelegate,
UINavigationControllerDelegate>) delegate {
...
self.cameraUI = [[UIImagePickerController alloc] init];
...
UIBarButtonItem *RecordBarButtonItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(recordPressed)]; // Removed the ':'
...
}
- (void) recordPressed {
NSLog(#"lets record");
[self.cameraUI startVideoCapture];
}
Actually I've just quickly tested it in some code I've gotten open, the sender for your action on the button press is UIBarButtonItem *. So there's a couple of things you can do, you can either go down the root of
UIBarButtonItem *senderButton = (UIBarButtonItem *)sender;
if(senderButton.image == UIBarButtonSystemItemCamera)
{
//Handle behaviour
}
Or set the tag variable for each button and skip the image check and look at the tags instead, which might make the logic a bit easier.
-(IBAction)startClick:(id)sender{
stick.highlighted = YES;
}
-(void)viewDidLoad{
[super viewDidLoad];
stick = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"ball1.png"]];
stick.userInteractionEnabled= YES;
stick.highlightedImage = [UIImage imagedNamed:#"ball2.png"];
[self.view addSubview:stick];
}
Button does not work after i type viewDidLoad method. Pls help. Thx. stick is linked to a uiimageview.
Hello as you said stick is linked to UIImageView , then it is a bit ambiguous. It's not clear whether you have declared an IBOutlet for this and connected to an UIImageview in xib or you have declared it as a variable in header file . There are two methods both of which works fine
Method 1:
Declare an IBoutlet in .h file and connect it to an Imageview in xib . Calling methods as follows
-(void)viewDidLoad{
[super viewDidLoad];
stick.image = [UIImage imageNamed:#"firstImage.png"];
stick.highlightedImage = [UIImage imageNamed:#"secondImage.png"];
}
-(IBAction)startClick:(id)sender{
stick.highlighted = YES;
}
would serve your purpose. The method is called from a button in xib on touch up inside event. In case you want to call this method from bar button all you need is to hook up selector of bar button to startclick method.
//2nd Method
If you have declared your Imageview in header as UIImageView* stick;
in viewDidLoad method you need to allocate it as
-(void)viewDidLoad{
[super viewDidLoad];
if (!stick) {
stick = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
[stick setImage:[UIImage imageNamed:#"firstImage.png"]];
[stick setHighlightedImage:[UIImage imageNamed:#"secondImage.png"]];
}
UIBarButtonItem* barButton = [[UIBarButtonItem alloc] initWithTitle:#"Click" style:UIBarButtonItemStylePlain
target:self action:#selector(startClick:)];
self.navigationItem.rightBarButtonItem = barButton;
[barButton release];
}
-(void)startClick:(id)sender{
stick.highlighted = YES;
}
Hope it helps !!
might be due to :
-(void)viewDidLoad
{
[super viewDidLoad];
stick = [UIImageView alloc]initWithImage:[UIImage imageNamed:#"ball1.png"];
stick.userInteractionEnabled= YES;
// stick.highlightedImage = [UIImage imaged:#"ball2.png"];
stick.highlightedImage = [UIImage imageNamed:#"ball2.png"];
[self.view addSubview:stick];
}
I am new to iPhone technology. I've saved a problem in a iPhone application, but when i use textfield keyboard type number pad the keyboard doesn't show a return/done button.
How can I hide the number pad keyboard after entering the number in the textfield? Do you have any solutions for that. Please provide help.
You can do this in this way:
#property (nonatomic, strong) UITextField *textField;
- (void)viewDidLoad {
[super viewDidLoad];
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonDidPressed:)];
UIBarButtonItem *flexableItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[self class] toobarHeight])];
[toolbar setItems:[NSArray arrayWithObjects:flexableItem,doneItem, nil]];
self.textField.inputAccessoryView = toolbar;
}
- (void)doneButtonDidPressed:(id)sender {
[self.textField resignFirstResponder];
}
+ (CGFloat)toolbarHeight {
// This method will handle the case that the height of toolbar may change in future iOS.
return 44.f;
}
you must be using UIKeyboardTypeNumberPad, try this instead UIKeyboardTypeNumbersAndPunctuation,
It'll not only show the return key but also provide you with some extra punctuations
There is no return or done key in number pad. You can do one thing when user touch outside of the textfield you can hide the keyboard. You should do something like this -
if (there is a touch outside of your textField)
{
[textField resignFirstResponder];
}
This question has already been answered, I know because thats how i got the solution. You have 2 options, first is to hide the keyboard by implementing a touch on the mainview that will send the "finished editing" message. that Hides the keyboard [self.view endEditing:YES];
If you do add the touch listener to the mainview you have to implement a condition so that any other buttons keep working.
What you do want to do to simulate a return key is to actually add it like this:
Register for a keyboard did show notification and add this to the code:
if ([self.passCodeLabel isFirstResponder])
{
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
//doneButton.frame = CGRectMake(0, 163, 257, 257);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:#"doneup.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"donedown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
NSLog(#"%#",[[UIApplication sharedApplication] windows]);
UIView* keyboard;
NSLog(#"Shared applicaiton windows count:%i",tempWindow.subviews.count);
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
NSLog(#"%#",[keyboard description]);
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:#"<UIPeripheralHostView"] == YES)
{
NSLog(#"Adding return button");
[keyboard addSubview:doneButton];
}
}
}
This will add your own "done" button image to the keyboard (which you can just copy by taking a screenshot of the screen of the blank slot and adding the done text).
Btw the code i pasted works on my layout. For yours you might have to modify it a bit, but the principle is the same.
Create the button
Look for the keyboard subview
Add the button to that subview
- (void)viewDidLoad
{
[super viewDidLoad];
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
numberToolbar.barStyle = UIBarStyleBlackTranslucent;
numberToolbar.items = [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneWithNumberPad)],
nil];
[numberToolbar sizeToFit];
_txt_mobileno.inputAccessoryView = numberToolbar;
}
-(void)doneWithNumberPad
{
[_txt_mobileno resignFirstResponder];
}
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?
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.
have you tried creating a UIButton in the button bar and then adding an activity indicator as a subView of the UIButton?
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.
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];