UIButton tapable area outside of subview - iphone

So I have a UIView which I call ctrView and this ctrView is added to my UIViewController's view. It's basically just a smaller rectangular frame inside. And I added a UIButton on the top right corner of this container view, however it seems that when clicking on the UIButton area which is a bit outside of the ctrView doesn't trigger the action tied to the button. Only the UIButton area that is inside the container view triggers the action. How do I resolve this weird issue?
UIButton *closeButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[closeButton setImage:[UIImage imageNamed:#"close.png"] forState:UIControlStateNormal];
[closeButton setBackgroundColor:[UIColor clearColor]];
[closeButton addTarget:self action:#selector(closeZoomedImageView) forControlEvents:UIControlEventTouchUpInside];
[closeButton setCenter:CGPointMake(ctrView.frameX + ctrView.frameWidth - 30, ctrView.frameY - 15)];
[ctrView addSubview:closeButton];
[closeButton release];

This is the normal behavior, views outside the bound of the parent will not receive touch actions
In order to fix this, rearrange the views like following
Main view will be big enough to accomodate the internal view and the closebutton, the backGroundColor of this view will be clear color
Internal view will be the view that will the internal view that will have the image and or the content of your normal view
Main view will have both the internal view and the close button as its childern
Main view will be big enough to accomodate the button
Main view will have a clear color background so that it will not affect the layout
So you will add all the views you currently have inside the internal view,
The internal view and the button view will both be added to the main view
you present then the main view to the viewcontroller

Related

UIButton does not respond to touch events after changing its position using setFrame

I have a view controller class (child) which extends from view controller class (parent). In the parent class's loadView() method I create a sub-view (named myButtonView) with two buttons (buttons are horizontally laid out in the subview) and add it to the main view. In the subclass I need to shift these two buttons up by 50pixels.
So, I am shifting the buttonView by calling the setFrame method. This makes the buttons shift and render properly but they do not respond to touch events after this. Buttons work properly in the views of Parent class type. In the child class type view also, if I comment out the setFrame() call the buttons work properly.
How can I shift the buttons and still make them respond to touch events?
Any help is appreciated.
Following is snippets of the code.
In the parent class:
- (void)loadView {
// Some code...
CGRect buttonFrameRect = CGRectMake(0,yOffset+1,screenRect.size.width,KButtonViewHeight);
myButtonView = [[UIView alloc]initWithFrame:buttonFrameRect];
myButtonView.backgroundColor = [UIColor clearColor];
[self.view addSubview:myButtonView];
// some code...
CGRect nxtButtonRect = CGRectMake(screenRect.size.width - 110, 5, 100, 40);
myNxtButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myNxtButton setTitle:#"Submit" forState:UIControlStateNormal];
myNxtButton.frame = nxtButtonRect;
myNxtButton.backgroundColor = [UIColor clearColor];
[myNxtButton addTarget:self action:#selector(nextButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[myButtonView addSubview:myNxtButton];
CGRect backButtonRect = CGRectMake(10, 5, 100, 40);
myBackButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myBackButton setTitle:#"Back" forState:UIControlStateNormal];
myBackButton.frame = backButtonRect;
myBackButton.backgroundColor = [UIColor clearColor];
[myBackButton addTarget:self action:#selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[myButtonView addSubview:myBackButton];
// Some code...
}
In the child class:
- (void)loadView {
[super loadView];
//Some code ..
CGRect buttonViewRect = myButtonView.frame;
buttonViewRect.origin.y = yOffset; // This is basically original yOffset + 50
[myButtonView setFrame:buttonViewRect];
yOffset += KButtonViewHeight;
// Add some other view below myButtonView ..
}
Button may have overlapped with another view after changing the frame... Just try by setting the background color to the views which are transparent so you can get clear idea which view is overlapping on button.
Make sure your UIButton’s container view can be interacted with. This is the one that gets me. If your UIButton is a subview of another view (not your view controller’s main view), it may not be configured to allow user interaction (the default). Try: containerView.userInteractionEnabled = YES;
Thanks for the help guys, you were right. I forgot to resize the scrollView that I added above the buttons, in the parent view. So, it was overlapping with the shifted buttonView. Changing the background color helped me see it. Thanks for the tip, Chandan.
This should work, my guess and this is just off the top of my head, is that you've got something intercepting your touch events. Basically, there's another view on top of your button.
Good luck.

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...

UIButton only responds in a small area

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.

UITextField leftView

Is it possible to set up a UITextField with a leftView so that if a user clicks into the UITextField the keyboard shows but if they click on an icon in the leftView another method is called (i.e., one that displays a UIPickerview)?
Have you checked that the leftFieldViewMode is set to something other than never
[textField setLeftViewMode:UITextFieldViewModeAlways];
Instantiate a button as u do normaly
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(0,0,30,30)];
[btn setTitle:#"title" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(BtnClick) forControlEvents:UIControlEventTouchUpInside];
Instantiate a textfield as you do normally
UITextField *txtfield1=[[UITextField alloc]initWithFrame:CGRectMake(10, 10,300,30)];
[txtfield1 setBackgroundColor:[UIColor grayColor]];
[txtfield1 setPlaceholder:#" Enter"];
To set a view in left side(there is right view also available)
[txtfield1 setLeftView:btn];
if u want the view to show always then below code does it
[txtfield1 setLeftViewMode:UITextFieldViewModeAlways];
if u want the view to show never then
[txtfield1 setLeftViewMode:UITextFieldViewModeNever];
if u want the view to show if the textfield is not edited then below
[txtfield1 setLeftViewMode:UITextFieldViewModeUnlessEditing];
if u want the view to show if the textfield is edited then
[txtfield1 setLeftViewMode:UITextFieldViewModeWhileEditing];
button click event and pop over
-(void)BtnClick
{
//Usual pop over coding goes here
}
Have you tried using a UIButton for this task? From the documentation for the leftView property:
If your overlay view does not overlap
any other sibling views, it receives
touch events like any other view. If
you specify a control for your view,
the control tracks and sends actions
as usual. If an overlay view overlaps
the clear button, however, the clear
button always takes precedence in
receiving events.
So create a UIButton instance, configure its appearance and actions as needed, then set it as the leftView property.

UIButtons over a UIImageView Zooming

I am pretty new to iphone programming. I just started about a month ago and have only been tinkering with small tutorial type applications but anyways, here is my question.
I currently have a UIScrollView thats scrollable and zoomable, that loads a UIImageView subview, and i want to add in some controls(UIButtons) over the image view but when i zoom in and out the whole group(the buttons and the image) zoom togeather.
If I add the UIButtons to my UIScrollView and zoom, the image zooms and the buttons stay in origional place
If I add the UIButtons to my UIImageView they zoom correctly but arent buttons anymore. IE they lose their interactivity.
Later ill add lots of buttons into an array and add them.
I would appreciate any help i can get
This is part of my mainViewController.m:
- (void)viewDidLoad
{
[scrollView2 setBackgroundColor:[UIColor blackColor]];
[scrollView2 setCanCancelContentTouches:NO];
scrollView2.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView2.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scroll2ImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bigNH.jpg"]];
[scrollView2 addSubview:scroll2ImageView];
[scrollView2 setContentSize:CGSizeMake(scroll2ImageView.frame.size.width, scroll2ImageView.frame.size.height)];
scrollView2.minimumZoomScale = .5;
scrollView2.maximumZoomScale = 3;
scrollView2.delegate = self;
[scrollView2 setScrollEnabled:YES];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect newSize = CGRectMake(658, 435, 50, 50); // position in the parent view and set the size of the button
myButton.frame = newSize;
[myButton setImage:[UIImage imageNamed:#"redStop.png"] forState:UIControlStateNormal];
// add targets and actions
[myButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
// add to a view
[scroll2ImageView addSubview:myButton];
[redLineArray addObject:myButton];
[scroll2ImageView release];
}
This might not help and it is not what it appears that you want to do.
However, when I want buttons associated with a scrollview, I add a parent view, add the buttons to that view and also add the scrollview to that view. The button(s) and the scrollview would be siblings. This allows the user to scroll around the contents of the scrollview, while insuring that the buttons are always in view.
-isdi-
By default, UIImageView has userInteraction disabled. Have you changed this?
Also, I would be really uneasy adding subviews to an UIImageView, it's really meant to hold one image. It would be better to create a normal UIView and add the UIButtons and UIImageView to that. It's very easy to control the ordering so that the buttons appears on top of the image.
P.S. Just to make your life easier, instead of :
[scrollView2 setContentSize:CGSizeMake(scroll2ImageView.frame.size.width, scroll2ImageView.frame.size.height)];
You can use :
[scrollView2 setContentSize:scroll2ImageView.frame.size];
Make a single view to contain all your zoomable content (everything it would appear), and call it say contentView. Now place everything you want in that contentView, the imageView and all your buttons etc.
In your UIScrollView delegate place this: (Be sure to set the scrollView's delegate if you haven't already)
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.contentView;
}
Only one view is allowed to zoom, but that one view can however contain other views that will scale because they're child views.
Also be sure to set the scrollView's contentSize value to the exact size of your zoomable contentView.