How to restrict rightBarButtonItem size in UINavigationBar? - iphone

I create a rightBarButtonItem with this method :
- (UIBarButtonItem *)customBarButtonWithSelector:(SEL)callback {
UIButton *customButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
customButton.bounds = CGRectMake(0, 0, 30.0f, 30.0f);
return [[[UIBarButtonItem alloc] initWithCustomView:customButton] autorelease];
}
At execution time the selector is fired when the bar is touched outside the button (near the middle).
Is there a way to restrict the event responder in the defined bounds or in a acceptable range ?

Try putting a fixed space before the button in the array of bar button items.

I have found the solution at http://osmorphis.blogspot.com/2009/05/multiple-buttons-on-navigation-bar.html
Really helpfull, don't forget to subclass UIToolBar.

Related

Set UIImageView background color upon user intervention

I am developing an application in which I have a horizontal scroller.
The scroller area comprise of different colors [which are nothing but UIImageView of colors].
Above the scroller area is a canvas [which is also a UIImageView].
Now, what I want is that when I select any color in the scroller area, it should set on the canvas.
It is pretty much like a color picker but I am already providing solid color options to be selected by the user.
How should I go about it ? Any sample Code to get me started or my mind kicking would be awesome ?
Thanx a ton
To implement it easily.
Use UIView not UIImageView
Set UIView backgroundColor and place it on the scroll
Set UITapGestureRecognizer on views,Refer here
when a purticular view is touched you have its instance of view which
is touched
get the background color of the view and set it in the scroller
Can you take UIButtons instead of UIImageViews inside your scrollView to show colours to be picked.
This will make the implementation easier. User will select any colour button and you will receive a callback in buttons action selector method. Then based on button tag or any property you can set the colour to your canvas.
In current implementation it will be tricky as you need to know the exact content offset where the tap is done to make out which UIImageView was pressed.
coding steps:
In your scroll view add UIButtons instead of UIImageView like:
UIButton* button = [[UIButton alloc] initWithFrame:someRect];
//put some tag to button
button.tag = someInt;
//add selector to each button to get callback
[view addTarget:self action:#selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
In the btnSelected method put this code:
-(IBAction)btnSelected:(id)sender;
{
UIButton* button = (UIButton*) sender;
if (button.tag == someInt) {
//do something like
canvas.backgroundColor = button.backgroundColor;
}
}
Instead of using UIImageViews or UIViews as suggested, I would put custom UIButtons for picking colors.
UIButton * colorButton;
//You will probably do these inside a for loop
colorButton = [UIButton buttonWithType:UIButtonTypeCustom];
[colorButton setFrame:CGRectMake(X, Y, buttonSize, buttonSize)];
[colorButton setTitle:#"" forState:UIControlStateNormal];
[colorButton setBackgroundColor:SOME_COLOR];
//Border visualization would be good if you are putting buttons side-by-side
[colorButton.layer setBorderWidth:1.0];
[colorButton.layer setBorderColor:[[UIColor darkGrayColor] CGColor]];
//You can use this tag to identify different buttons later
[colorButton setTag:INDEX+SOME_OFFSET]; //use loop index with some offset
[colorButton addTarget:self action:#selector(colorButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
-(void) colorButtonPressed:(UIButton *) sender
{
UIColor *selectedColor = sender.backgroundColor; //Or identify with sender.tag
[yourCanvas doSmtOnCanvas:selectedColor];
}
Initialize UIImageView then add gesture recognizer to all imageViews by calling this method.
- (void) setupImageView : (UIImageView *) imageView{
[imageView setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(changeUIImageViewBackgroundColor:)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[imageView addGestureRecognizer:tapGestureRecognizer];
}
Now change color of canvasView within the selector by following way:
- (void) changeUIImageViewBackgroundColor : (UITapGestureRecognizer *) recognizer{
UIImageView *imageView = (UIImageView *)[recognizer view];
[canvasView setBackgroundColor:[imageView backgroundColor]];
}
You can put a tap gesture in your scrollview and whenever a tap is made in the scroll check whether the tap is on the imageview. (You will get whether the tap point in on imageview or not) and according you can change the image.
Second alternative is to take a custom button and handle on its click.
Hope it helps

How to make toggle image button instead of UIBarButtonItem in iphone programming?

I have to make a button in UINavigationBar, the button should toggle between restart state and cancel state, and it should call
-(void)RestartMethod {}
at restart state and should call method
-(void) cancelMethod {}
at cancel state of UIBarButtonItem,both states are using images like start.png and calcel.png
I tried by making two images and add and remove targets,b but facing some bad-exec issues,
how can I do it?
Help!
item1=[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"DoneUp3.png"] style:UIBarButtonItemStylePlain target:self action:#selector(action1)];
item2=[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:#"Pin.png"] style:UIBarButtonItemStylePlain target:self action:#selector(action2)];
-(void)action1{self.navigationItem.rightBarButtonItem = item2;}
-(void)action2{self.navigationItem.rightBarButtonItem = item1;}
Create two buttons with two different targets. When one button is clicked do whatever you want the action to be and replace the button with button number two. If button number two is clicked, replace that with button number 1.
Why not use a segment control instead of toggle button? Even if you insist on using a single button to toggle, this is how I would achieve it.
Have a bool declare the initial state
BOOL buttonOn = NO;
Embed the first button with initial image pointing to one selector
Inside selector take action based on this boolean. Change state and change this boolean's value too. No need to have two different selectors. Call appropriate functions to do stuff inside this selector.
i think this can help you:
CGRect frameimg = CGRectMake(0, 0, image3.size.width, image3.size.height);
UIButton *someButton = [[UIButton alloc] initWithFrame:frameimg];
[someButton setBackgroundImage:[UIImage imageName:#"start.png"] forState:UIControlStateNormal];
[someButton setBackgroundImage:[UIImage imageName:#"calcel.png"] forState:UIControlStateSelected];
[someButton addTarget:self action:#selector(backButtonPress:)forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *mailbutton =[[UIBarButtonItem alloc] initWithCustomView:someButton];
self.navigationItem.leftBarButtonItem=mailbutton;
[mailbutton release];
New write backButtonPress: method:
-(void)backButtonPress:(id)sender{
UIButton *tmpButton = (UIButton *)sender;
tmpButton.selected = [tmpButton isSelected]?NO:YES;
if (tmpButton.selected) {
// call cancelMethod or write RestartMethod code here
}
else{
// call RestartMethod or write RestartMethod code here
}
}

How to add Activity Indicator as subview to UIButton?

Can we add activity indicator as subview to UIButton?
If yes then plz tell me how to do that?
I used [button addSubview:activityIndicator];
Not working...
I found that adding a UIActivityIndicatorView to a UIButton was a really useful method to allow users to know something is happening without having to use the MBProgressHUD (I think the HUD is really good but should not be used in all situations.
For this reason I created two functions:
I have already allocated my UIButton so it is a class variable called _confirmChangesButton
I then create my activity indicator, set its frame (taking into account the button size) and then adding the indicator is easy.
- (void)addActivityIndicatorToConfirmButton {
// Indicator needs to be in the middle of the button. So half the screen less half the buttons left inset less half the activity indicator size
CGRect rect = CGRectMake([UIScreen mainScreen].bounds.size.width/2 - 10 - 15, 5, 30, 30);
UIActivityIndicatorView * activity = [[UIActivityIndicatorView alloc] initWithFrame:rect];
activity.hidesWhenStopped = YES;
[_confirmChangesButton setTitle:#"" forState:UIControlStateNormal];
[_confirmChangesButton addSubview:activity];
[activity startAnimating];
}
Having a removal function is also useful if you are using blocks. It might be that the completion task comes back with a failure and so we want to remove the indicator and change the title back. In this function we need to make sure to remove the indicator and not the button label which is the other subview on this button.
- (void)removeActivityIndicatorFromConfirmButton {
UIActivityIndicatorView * activity = _confirmChangesButton.subviews.lastObject;;
[activity removeFromSuperview];
[_confirmChangesButton setTitle:#"Confirm Change" forState:UIControlStateNormal];
}
I found that using these two you can create a much better user experience letting the user know what is going on when they press buttons.
Hope this helps
Use the below code below to add acitivity indicator a button or any uiview object
UIActivityIndicatorView *aView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
aView.frame = CGRectMake(0, 0, {yourButton}.frame.size.width, {yourButton}.frame.size.height);
aView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
[{yourButton} addSubview:aView];
[aView startAnimating];
Hope this will help..
I don't think it's possible to add a view to a button. UIButton have this method because it's inherited from UIVIew.
The real question is : why do you want to add an activity indicator on a button and not elsewhere ?
did you do [activityIndicator startAnimating]; ALso as u are using it in a tableview just check if the tags are set properly

Hit target on UIToolbar with custom-image buttons is not correct

I have a UIToolbar that I've customized with my own background image. Consequently, the built-in UIBarButtonItem appearance doesn't work for me, so I'm using images that are already prepared to show in the bar. I create a custom button item with this method:
+ (UIBarButtonItem *)customWithImage:(UIImage *)image enabled:(BOOL)enabled target:(id)target action:(SEL)selector {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//I've tried different values for the frame here, but no luck
button.frame = CGRectMake(0, 0, 44, 44);
button.enabled = enabled;
button.showsTouchWhenHighlighted = YES;
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
[button setImage:image forState:UIControlStateNormal];
UIBarButtonItem *it = [[[UIBarButtonItem alloc] initWithCustomView:button] autorelease];
//Tried changing this, to no avail
it.width = 32.f;
return it;
I have one button on the left and one on the right and I'm trying to make it so that if you tap on the far left or far right of the UIToolbar, the corresponding button is tapped. However, with these custom buttons, the hit targets do not extend all the way to the edges of the UIToolbar, but are inset from the sides:
http://skitch.com/andpoul/d1p8g/hit-targets
Any help greatly appreciated!
UIBarButtonItem.width might be ignored if you're using a custom view (it probably just uses the width of the view).
A lame hack is to make the toolbar wider (so it sticks outside the screen) and add transparent edges to the background image to compensate. This brings the buttons closer to the edge of the screen.
An alternative is just to use a UIImageView with UIButton subviews.
I think the only way you will have to go is to make buttons wider (change image by adding some from left for one and right for another) and adjust size...

iPhone : making UIBarButtonItem that is arrow shaped

I have a UIBarButtonItem on a navigation bar. I'd like to make it arrow shaped. By that I mean I want it to be square except for a pointy side. Does anyone know how to do this?
Thanks!
I wrestled with several approaches on this one and finally figured it out using all the answers from several sources. There are a couple of tricks; this snippet will show it all (I was creating a custom rightNavButton, but you can adapt this easily for any UIBarButtonItem):
// Produces a nice "right arrow" style button that mirrors the back arrow
// automatically added by the navController
//
UIImage *buttonImage = [UIImage imageNamed:#"forwardButton.png"];
UIButton *forwardButton = [UIButton buttonWithType:UIButtonTypeCustom];
[forwardButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
[forwardButton setTitle:#"Meter" forState:UIControlStateNormal];
forwardButton.font = [UIFont boldSystemFontOfSize:12];
forwardButton.frame = CGRectMake(0, 0, buttonImage.size.width, buttonImage.size.height);
[forwardButton addTarget:self action:#selector(showMeter)
forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithCustomView:forwardButton];
Note: it turns out that if you try to set the target and action directly on the button item after assigning a custom view using a UIButton that it won't take - you have to set the target and action on the button itself - apparently the navBar uses the button provided verbatim.
This is the image I was using on the opaque black navBar (you can use anything, obviously): http://raretiger.com/images/forwardbutton.png
Make a custom background. See Creating a left-arrow button (like UINavigationBar's "back" style) on a UIToolbar for how.
You may -pushNavigationItem:animated: to make the built-in back button appear, although you cannot assign custom actions to it.
For undocumented methods, you may use
UIButton* backButton = [UIButton buttonWithType:101];
to create a back "button".
You could create an UIImageView or an UIButton with the required image then use:
[[UIBarButtonItem alloc] initWithCustomView: arrowButton];
Hope this helps.
continuing on #Plamen Dragozov's idea: i noticed if you leave the uibutton as is, it would trigger a picture adjustment when touched and that is quite the opposite what a normal navigation back button does. So what I did was to uncheck "highlighted adjusts Image" and it works like a charm.
hope this helps newbies like me.
More elegant solution:
UIBarButtonItem * backButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Title" style:UIBarButtonItemStylePlain target:self action:#selector(back:)];
[backButtonItem setBackgroundImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
self.navigationItem.leftBarButtonItem = backButtonItem;
My problem was renaming the back button that appears on the pushed view controller. I found a dirty workaround and if you ignore the non-ideal animation problem, you'll get a back button with the title you want.
The trick is to change the title of the first VC in viewWillDisappear and re-set it of course in viewWillAppear
(Needless to say, by default, if there is no leftBarButtonItem set, UINavigationController will show a back button with the title of the VC that pushed the current VC)
In the VC where you push your current VC, do
-(void) viewWillDisappear:(BOOL) animated {
[super viewWillDisappear:animated];
self.title = #"Back";
}
-(void) viewWillAppear:(BOOL) animated {
[super viewWillAppear:animated];
self.title = #"Original Title";
}