Is it possible to have a UIBarButtonItem as a cell accessoryView? - iphone

I have a tableview, where one of the cells is supposed to display a thumbnail image. However, if that image is not available (hasn't been taken yet), I'd LIKE for the cell's accessoryView to display the camera UIBarButtonItem...but when I try my usual approach I get 'incompatible types' warnings. Is there any way to use those items outside of a nav bar?

It is not possible to directly use UIBarButtonItem as the cell's accessoryView, because UIBarButtonItem is not a UIView.
A suboptimal solution could be to use a UIToolbar to hold your UIBarButtonItem. You can then add the UIToolbar as the cell's accessoryView, but you'll end up with the unwanted outline of the UIToolbar. This SO answer explains how to make a transparent UIToolbar subclass. That way you won't see the toolbar's background, but you'll also lose the outline of the UIBarButtonItem - it will only show the white camera icon:
UIToolbar *toolbar = [[TransparentToolbar alloc] init];
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(someAction)];
toolbar.frame = CGRectMake(0, 0, 40, 30);
[toolbar setItems:[NSArray arrayWithObject:item] animated:NO];
cell.accessoryView = toolbar;
[item release];
[toolbar release];

I think that is impossible. Since it is called BarButtonItem it can only go into a bar. The old method allthough works: Take a screenshot of the camera button (just add it to any navigationbar for the screenshot), cut it out from the screenshot, add a regular UIButton to your cell and add the image of your camera button as backgroundimage for your UIButton using
[button setBackgroundImage:[UIImage imageWithImage:#"camerabutton.png"] forState:UIControlStateNormal];
And also take a screenshot of the button when its pressed and save it and set it as image for selected state:
[button setBackgroundImage:[UIImage imageWithImage:#"camerabuttonpressed.png"] forState:UIControlStateHighlitedl];

Related

Use Image for backBarButtonItem with NO TEXT

I'm simply trying to set the backBarButtonItem for my navigation controller to this image
instead of the Apple default arrow button whose title is the same as the previous view controller's title. The closest I've gotten so far is the above image stretched horizontally with the title still appearing overlaid. To get that, I used this code in my AppDelegate.
UIImage *backButtonImage = [UIImage imageNamed:#"back-button.png"];
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
How can I get rid of the title (and prevent the button from being stretched)?
When you use appearance, you are setting the background image of the back bar button items of your app. The fact that they have a background image has nothing to do with whether or not there is a title displayed on them. To use a custom bar button item instead of the default back item, look at this question.
In your case, you may want to not use appearance at all and instead create a bar button item as in the link above but use -initWithImage:style:target:action: instead of -initWithTitle:style:target:action:
you can set custom Image of BarbuttonItem like :-
- (void)viewDidLoad
{
UIImage* imageRight = [UIImage imageNamed:#"Home_btn.png"];
CGRect frameimgRight = CGRectMake(100, 100, 50, 30);
RightBtn = [[UIButton alloc] initWithFrame:frameimgRight];
[RightBtn setBackgroundImage:imageRight forState:UIControlStateNormal];
[RightBtn addTarget:self action:#selector(ActionhomeBtn)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *btnRight = [[UIBarButtonItem alloc]initWithCustomView:RightBtn];
self.navigationItem.leftBarButtonItem = btnRight;
[super viewDidLoad];
}
Look like:-
Hope its halp's you
I know this method works, and should be called in ViewDidLoad:
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"back-button.png"] style:UIBarButtonItemStyleBordered target:nil action:#selector(methodName)];
which then has to be assigned to the nav bar:
item.rightBarButtonItem = backButtonItem;
and then pushed:
[self.navBar pushNavigationItem:item animated:NO];

UIBarButton with CustomView and a Border

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.

are customViews for UIBarButtonItems ignored for the leftBarButtonItem

From the documentation, I see this for the backBarButtonItem:
When this property is nil, the navigation item uses the value in its
title (page 10) property to create an appropriate back button. If you
want to specify a custom image or title for the back button, you can
assign a custom bar button item (with your custom title or image) to
this property instead. When configuring your bar button item, do not
assign a custom view to it; the navigation item ignores custom views
in the back bar button anyway.
I didn't know if this was the same for leftBarButtonItem? Basically I have this code:
UIButton *homeButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
UIImage *homeImage = [UIImage imageNamed:#"icon_house.png"];
[homeButton setImage:homeImage forState:UIControlStateNormal];
[homeButton addTarget:self action:#selector(homePressed:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *homeBBI = [[UIBarButtonItem alloc] initWithCustomView:homeButton];
Prior to iOS 5, I put this in a UIToolBar and it showed up fine. Now I want to put this as the leftBarButtonItem, to the right of the UINavigationController's backButton. When I set it, it does not show up at all. There is no image. However, when I create some button like this:
UIBarButtonItem *hButton = [[UIBarButtonItem alloc] initWithTitle:#"home" style:UIBarButtonItemStylePlain target:self action:#selector(homePressed:)];
and set it as the leftBarButtonItem, it shows up. I didn't know how I could get my custom icon for my home button without the borders. When I use:
UIBarButtonItem *hButton2 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"icon_house.png"] style:UIBarButtonItemStylePlain target:self action:#selector(homePressed:)];
I get a border around my house_icon that i do not want. Thanks.
try this
UIButton *TastoVersamento = [UIButton buttonWithType:UIButtonTypeCustom];
[TastoVersamento setImage:[UIImage imageNamed:#"Versamento.png"] forState:UIControlStateNormal];
[TastoVersamento addTarget:self action:#selector(Click_Versamento:) forControlEvents:UIControlEventTouchUpInside];
[TastoVersamento setFrame:CGRectMake(0, 0, 40, 40)];
[[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithCustomView:TastoVersamento] autorelease]];
backBarButtonItem and leftBarButtonItem are different. backBarButtonItem is the default if no leftBarButtonItem is given. It will also show up even if leftBarButtonItem is set if leftItemsSupplementBackButton is YES.
In your first example, you could try [homeButton sizeToFit]. I think the frame may not be getting set correctly.
But as to your last comment, I think you won't be succesful in removing the border from navigation item buttons. I'm pretty sure they're hard coded. In fact, if you add a button that has a border, you'll get two, one from the button and one from the navigation item.

How to remove/avoid small white splash light on UIBarButtonItem programmatically

My issue is same as question: How to disable the the light that appears when touching a UIBarButtonItem?
I have read answer if we use Interface builder. What if I add toolbar programmatically? How can I avoid the light on the bar button item?
To do what you want programatically you can do
UIBarButtonItem *item;
UIButton *b2=[[UIButton alloc] initWithFrame:frame];
[b2 addTarget:self action:#selector(settings:) forControlEvents:UIControlEventTouchUpInside];
//you can set the background image or whatnot
[b2 setBackgroundImage:[UIImage imageNamed:#"settings.png"] forState:UIControlStateNormal];
item=[[UIBarButtonItem alloc] initWithCustomView:b2];
//then set the button on the UIToolbar through the items property

Rotate UIBarButtonItem

I want to rotate a UIBarButtonItem.
I have been able to do this with UIButtons using setTransform:CGAffineTransformMakeRotation(…), but UIBarButtonItem does not have this property.
I know the Camera-app does this, so it should be achieveable.
How can I achieve this?
Thanks.
Have you tried using a custom view inside the UIBarButtonItem that you then transform any way you want?
UIBarButtonItem does not extend UIView, so it cannot be transformed directly. You can add the UIBarButtonItem you wish to transform to a UIToolbar, transform the UIToolbar and then add the toolbar as a custom view to another UIBarButtonItem. This item can then be set as a navigation item or added to another UIToolbar. However, if you are using a custom view or image then Emil's approach in the comment above is best.
UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target:self action:#selector(handleForwardItemTouch:)];
UIToolbar *backToolbar = [[[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 44, 44)] autorelease];
[backToolbar setTransform:CGAffineTransformMakeScale(-1, 1)];
UIBarButtonItem *backToolbarItem = [[[UIBarButtonItem alloc] initWithCustomView:backToolbar] autorelease];
self.navigationItem.rightBarButtonItem = backToolbarItem;
You could put a UIButton inside a Bar Button Item, than rotate the UIButton.
I extended UIToolBar, giving access to its subviews, and in it have a function rotate that rotates the buttons in the opposite direction of the bar:
- (void)rotate: (int)degrees{
//for the bar
self.transform=CGAffineTransformMakeRotation(DegreesToRadian(degrees));
//for the subviews (UIBarButtonItems)
for (UIView * subView in self.subviews)
{
if(!CGRectEqualToRect(subView.bounds, self.bounds))
subView.transform = CGAffineTransformMakeRotation(DegreesToRadian(-degrees));
}
}