UIBarButton with CustomView and a Border - iphone

I've subclassed UIBarButtonItem and am trying to make a button which dispays a refresh image normally, but an activity spinner when loading. The problem I have is I can't get the bordered style to display a custom view inside. It just doesn't appear.
This is my code (from my UIBarButtonItem subclass's constructor):
self = [super initWithTitle:#"" style:UIBarButtonItemStyleBordered target:self action:nil];
UIView *viwInner = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 24,24)];
[self.customView addSubview:viwInner];
self.btnStandard = [UIButton buttonWithType:UIButtonTypeCustom];
[self.btnStandard setFrame:CGRectMake(0, 0, 24,24)];
UIImage *initialImage = [[UIImage imageNamed:#"refresh_24.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[self.btnStandard setBackgroundImage:initialImage forState:UIControlStateNormal];
[self.btnStandard setBackgroundImage:initialImage forState:UIControlStateHighlighted];
[self.btnStandard setBackgroundImage:initialImage forState:UIControlStateSelected];
[self.btnStandard addTarget:self action:#selector(didTapInitialButton:) forControlEvents:UIControlEventTouchUpInside];
[viwInner addSubview:self.btnStandard];
self.btnLoading = [UIButton buttonWithType:UIButtonTypeCustom];
[self.btnLoading setFrame:CGRectMake(0, 0, 24,24)];
self.loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActionSheetStyleBlackOpaque];
[self.loadingView setHidesWhenStopped:true];
[self.loadingView stopAnimating];
[self.btnLoading addSubview:self.loadingView];
[self.btnLoading addTarget:self action:#selector(didTapAbortButton:) forControlEvents:UIControlEventTouchUpInside];
[viwInner addSubview:self.btnLoading];
return self;
Is there a reason this isn't working?

In iOS5, there is a trick to get an animated image into a UIBarButtonItem and maintain the UIBarButtonItemStyleBordered:
UIImage *image = [UIImage animatedImageNamed:#"refresh-" duration:1.f];
self.button = [[UIBarButtonItem alloc] initWithImage:image
style:UIBarButtonItemStyleBordered
target:self
action:#selector(doSomething:)];
Then, create a set of images, one image for each frame of the animation, and name then "refresh-0.png", "refresh-1.png" and so forth:
When you want to stop the animation, replace the image of the button with a static version:
self.button.image = [UIImage imageNamed:#"refresh-0.png"];
It's still a significant hassle having to create all these images yourself, but it's probably more consistent than creating your own Button-border background.

To accomplish this using UIActivityIndicatorView, rather than your replacement for it, you have to render the button border yourself. What I do is set the UIBarButtonItem's customView to a UIImageView containing the border, and add the activity view as a subview of that image.
That leaves you with the problem of getting the border image. If you only need it on one bar color, then you can just crop it out of a simulator screenshot; if you need it on multiple bar colors, then you'll want to get not just border pixels, but also border transparency, for which I wrote a Python script.

It is not possible to do what you are trying to do as UIBarButtonItems (created with -initWithImage:style:target:action: or -initWithTitle:style:target:action:) don't support arbitrary views inside the button.
You could try placing the the UIActivityIndicatorView on top of a image that simulates the border of a button. You could then use initWithCustomView: to add the view to your button.
Hope this helps.

Related

How to remove space from UINavigationbar between Button

How to remove this space image here. Here is my code :
UIButton *postButton = [UIButton buttonWithType:UIButtonTypeCustom];
[postButton setImage:[UIImage imageNamed:#"post_btn.png"] forState:UIControlStateNormal];
postButton.frame = CGRectMake(0, 0, 44, 44);
[postButton addTarget:self.viewDeckController action:#selector(postAction:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:postButton];
thx for help.
As standard, you can't. And the cost of doing so is likely to be prohibitive as you would need to create your own custom navigation bar (or subclass) and manage the drawing yourself.
That said, the gap is there for a reason as touch detection isn't so accurate near the edge of the screen and fingers are big...
First there is no need to use UIButton but we can. you can use it UIBarButtonItem
UIImage *myImage = [UIImage imageNamed:#"post_btn.png"];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:myImage style:UIBarButtonItemStyleBordered target:self action:#selector(postAction:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
As standard, you can't. but you can set manually.
1- setNavigationBarHidden hidden.
[self.navigationItem setNavigationBarHidden:TRUE];
2- Take one UIImageView size = 320 X 45. //as per your required height
3- set your button on it. make it height smaller then above image.

UIBarButtonItem:setBackgroundVerticalPositionAdjustment not working properly with custom button

I have the following code to customize the display of an UIBarButtonItem (locationButton):
UIButton *locationButtonAux = [UIButton buttonWithType:UIButtonTypeCustom];
[locationButtonAux setFrame:CGRectMake(0, 0, LOCATION_BUTTON_WIDTH, LOCATION_BUTTON_HEIGHT)];
[locationButtonAux setBackgroundImage:[UIImage imageNamed:#"location_button.png"] forState:UIControlStateNormal];
[locationButtonAux setBackgroundImage:[UIImage imageNamed:#"location_button.png"] forState:UIControlStateHighlighted];
[locationButtonAux addTarget:self action:#selector(userLocation) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *locationButton = [[UIBarButtonItem alloc] initWithCustomView:locationButtonAux];
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:#"title"
style:UIBarButtonItemStyleDone
target:nil action:#selector(someMssage)];
[locationButton setBackgroundVerticalPositionAdjustment:-20.0 forBarMetrics:UIBarMetricsDefault];
self.navigationItem.rightBarButtonItem = locationButton;
And I want to adjust the position of this button into the NavigationBar, because my NavigationBar is taller than normal (is customized using Appeareance).
I'm using the method setBackgroundVerticalPositionAdjustment, as you can see in the code, to do that. But is not working at all with my UIBarButtonItem, no matter what offset I put there, the button always appear close to the bottom of the bar (snapshot).
BUT, if I use a normal UIBarButtonItem with a normal style (the one I called button) I DO can see how the position of the button will be altered the offset of -20. Very strange... Any ideas?
Thank you!
Perhaps something like this would work for you:
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 30)]; //change this frame to counteract for your taller navbar
[rightView addSubview:locationButtonAux];
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightView];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
Hope this helps
You need to put the button inside a blank view and position it within that blank view. Now make that view the custom view of the bar button item.
You really don't need a button here, since this is just an image and you are not using any of the button capabilities (you can attach a gesture recognizer to spot the tap). So here's a simple solution using an image view:
UIImageView *locationButtonAux =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"location_button.png"]];
UIView* v = [[UIView alloc] initWithFrame:locationButtonAux.frame];
[v addSubview:locationButtonAux];
CGRect f = locationButtonAux.frame;
f.origin.y -= 10;
locationButtonAux.frame = f;
UIBarButtonItem *locationButton = [[UIBarButtonItem alloc] initWithCustomView:v];
self.navigationItem.rightBarButtonItem = locationButton;
I've omitted the gesture recognizer part but you can easily see how to add it.

adding custom UIButton to UINavigationBar

So the code I have is as follows:
// Create a containing view to position the button
UIView *containingView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 23.5, 21.5)] autorelease];
// Create a custom button with the image
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"Settings.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(settings) forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(-19, -3, 21.5, 21.5)];
[containingView addSubview:button];
// Create a container bar button
UIBarButtonItem *containingBarButton = [[[UIBarButtonItem alloc] initWithCustomView:containingView] autorelease];
self.navigationItem.rightBarButtonItem = containingBarButton;
The issue is that my Settings.png original image size is 21.5, 21.5 and there fore the button is super hard to click. I have to tap really hard in order to trigger the UITouchUpInside to be triggered. This will clearly be rejected if I put it in the app store, as it is not in compliance with apple's HIG. Is there a way around this? I still need to use UIView as the container for the UIButton as I'd like to position it correctly on the UINavigationBar
Try to set a bigger fram to the button like 40,40 and set the content mode to be the center so the image will apear to be in the center.
button.contentMode = UIViewContentModeCenter;
Tell me if that helped

iPhone SDK: UIBarButtonItem is not displaying border

I have a UIToolbar which I am trying to put some custom UIBarButtonItems on. However, when I use the code below, the button shows up with NO border.
UIImage *cameraRollButtonImage = [UIImage imageNamed:#"Flash.png"];
UIButton *cameraRollButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cameraRollButton setImage:cameraRollButtonImage forState:UIControlStateNormal];
cameraRollButton.frame = CGRectMake(0.0, 0.0, cameraRollButtonImage.size.width, cameraRollButtonImage.size.height);
// Initialize the UIBarButtonItem
cameraRollButtonItem = [[UIBarButtonItem alloc] initWithCustomView:cameraRollButton];
[cameraRollButtonItem setStyle:UIBarButtonItemStyleBordered];
//Add the Buttons to the toolbar
NSArray *toolbarItems = [NSArray arrayWithObject:cameraRollButtonItem];
[self.cameraTabBar setItems:toolbarItems];
This displays the button just fine, however, there is NO button border (like standard the UIBarButtonItem). So the line [cameraRollButtonItem setStyle:UIBarButtonItemStyleBordered]; doesn't seem to do anything.
Does anyone have any experience with this?
I would like to be able to eventually rotate the image in the button when the device orientation is changed (keeping the toolbar static), so simply adding an image to the UIBarButtonItem doesn't work; I need to get this to work with by using the customView property.
Many thanks!
Brett
Have you considered creating your own button image with a border? You can use it as the backgroundImage of a UIButton:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:_backgroundImage_ forState:UIControlStateNormal];
// So that the button does not gray out when disabled
[button setBackgroundImage:_backgroundImage_ forState:UIControlStateDisabled];
[button setImage:_cameraImage_ forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 125, 30);
You could then use button with initWithCustomView:.
The PSD file here might give you an overview of how to create your own button.

Allow a UIBarButtonItem to touch top & bottom of UINavigationBar

Take a look at the Droplr iPhone app:
Notice how the UIBarButtonItems are able to touch the right, left, top, and bottom of the screen/navigation bar?
How can I achieve something similar? Here's how I make a sample UIBarButton and set it to the right item:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.frame= CGRectMake(0.0, 0.0, image.size.width, image.size.height);
[button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *bb = [[[UIBarButtonItem alloc] initWithCustomView:button]autorelease];
[self.navigationItem setRightBarButtonItem:bb animated:YES];
However, it is not right aligned, and has quite a bit of margin from the top & the bottom. My image size is correct (44px), and it looks like it shrinks it to fit a frame of sorts.
So, how can I do this?
Edit: Whoops, the top/bottom spacing was my fault. However, I can't figure out how to align the bar button flush with the left/right side. Here's what I mean: (sorry for the ugly button, it was just a test)
I tried setting the image inserts, but it didn't seem to do anything.
UIView *rightview = [[UIView alloc] initWithFrame:CGRectMake(0,0,30,30)];
UIButton *searchbutton = [[UIButton alloc] initWithFrame:CGRectMake(2,2,50, 30)];
[searchbutton setImage:[UIImage imageNamed:#"some-pic.png"] forState: UIControlStateNormal];
[rightview addSubview:searchbutton];
UIBarButtonItem *customItem = [[UIBarButtonItem alloc] initWithCustomView:rightview];
self.navigationItem.rightBarButtonItem = customItem;
[customItem release];
I use a customView for the rightBarButtonItem and I get it right aligned.
Just try a bit with the CGRectMake-Numbers for the x-coordinate, for testing I added to high numbers...