I'm building a menu as a subclass of UIControl that opens when a user touches it and will close if a user doesn't choose one of its options.
I'm looking for a way to track when a user touches outside so that I can close the menu
Put one view behind your menu that cover whole area of your device with background of clear color. when your menu is open make that view visible. as it has same height and width as your device whenever you click outside the menu you can identify that view using TapGesture or make it UIControl. than call method to hide both your menu and that uiview.
Hope this will help.
What I really like to do is to make a big button that covers the entire view, and have it below the menu, or whatever else I want to touch away from and have something happen.
UIButton *bigBackButton = [[UIButton alloc]initWithFrame:self.view.frame];
[bigBackButton addTarget:self action:#selector(backButtonSelected) forControlEvents:UIControlEventTouchDown];
[bigBackButton setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]];
[self.view addSubview:bigBackButton];
}
- (void)backButtonSelected:(UIButton *)button {
//get rid of the button
[button removeFromSuperview];
//do whatever else you need to do
[yourmenu dosomething];
}
on some apps, I'll make the button dark and translucent to highlight the menu, whatever else. Other times I'll make it pretty much invisible, like [UIColor colorWithWhite:1.0 alpha:0.01];
in your menu routine you could add these same routines. You could pass the frame of the parent view, or just look it up in the layoutSubviews routine, if your menu is a sublcass of a UIView.
in your layoutSubviews, add this:
UIButton *bigBackButton = [[UIButton alloc]initWithFrame:self.superview.frame];
[bigBackButton addTarget:self action:#selector(backButtonSelected) forControlEvents:UIControlEventTouchDown];
[bigBackButton setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.5]];
[self.view addSubview:bigBackButton];
and then put the backButtonSelected method in your menu class as well.
Related
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
I have a tableview that contains a row with a custom cell that contains a UIButton. However, the button doesn't always fire the action. Here's my code:
submitButton = [[UIButton alloc] init];
[[submitButton layer] setBorderColor:[[UIColor whiteColor] CGColor]];
[submitButton setClipsToBounds: YES];
submitButton.backgroundColor = [UIColor grayColor];
[submitButton setTitle:#"Send" forState:UIControlStateNormal];
[self.contentView addSubview:submitButton];
[submitButton addTarget:self action:#selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[submitButton release];
This is called in the custom cell's -(id)initWithStyle:
The buttonAction method looks like this:
-(void)buttonAction
{
NSLog(#"Button Clicked!");
}
It seems that the only way I can get the buttonAction to fire is if I press down on the button and release somewhere inside the cell's frame, but not inside the button itself. Why would that be?
*UPDATE*
Problem still exists, but I found that the more consistent way to get the button to fire is to click and drag to the left or right and then let go, as long as I let go within the bounds of the cell/row.
UPDATE #2
It looks like if I use iOS 6.0, it works as intended. But on 5.0 or 5.1 it does not.
Try assigning the same method call to TouchUpOutside as well - you should then see it work every time. TouchUpInside is only fired if you lift your finger while still within the bounds of the button.
Try [submitButton sizeToFit]. I'm wondering whether your button has any size (since I don't see you giving it any).
Also: Create your button with [UIButton buttonWithType: UIButtonTypeCustom] instead of alloc-init.
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
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...
I'm trying to add a UIButton to a UIView, but am having some trouble with getting it to respond to touches.
I have a method which returns UIButtons after I provide it with a tag:
- (UIButton*)niceSizeButtonWithTag:(int)tag {
UIButton * aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setTag:tag];
[aButton addTarget:self action:#selector(buttonWasTapped:) forControlEvents:UIControlEventTouchUpInside];
CGRect newFrame = aButton.frame;
newFrame.size.width = 44;
newFrame.size.height = 44;
[aButton setFrame:newFrame];
return aButton;
}
As you can see I'm creating a new button and increasing the size.
I use this in the following way:
UIButton * anotherButton = [self niceSizeButtonWithTag:1];
[anotherButton setImage:[UIImage imageNamed:#"image" withExtension:#"png"] forState:UIControlStateNormal];
[anotherButton setCenter:CGPointMake(middleOfView)];
[aView addSubview:anotherButton];
I create a lot of buttons like this, hence the reason for the method.
The buttons are always created and added to the subview perfectly. I can see the image and they're in the correct position. The problem is that they only respond to touches in a tiny strip.
In this attached image,
alt text http://web1.twitpic.com/img/107755085-5bffdcb66beb6674d01bb951094b0e55.4c017948-full.png
The yellow shows the whole frame of the button,
The red shows the area that will respond to touches.
The grey shows a section of the view the button is added to.
If anyone could shed some light on why this is happening, it would be really useful.
UPDATE:
I should probably mention I'm trying to add this button to a UIView which is a subview of a UITableViewCell.
UPDATE 2:
Adding it directly to the UITableViewCell works, adding it to the UIView on the UITableViewCell is causing the error.
FINAL UPDATE
The problem turned out to be that I was sending the view containing the button to the back of the subviews on the UITableViewCell. Getting rid of the sendSubviewToBack: call fixed it.
Do you have any other views added to this containing view after you add the button? try setting some of your view's background color to blueColor, redColor and other colors to better see what the stack of views in your app is like. Then you should be easily able to see if there is some sort of view blocking the button.