I have a view with some UIButtons on it. I add another - semi transparent - view on top of all, displaying some information to the user (actually, it's kind of a selfmade modal-alert). But the buttons under the semi-transparent view still react to taps. They shouldn't, though.
How can I prevent the buttons from reacting to taps?
Setting,
semiTransparentViewOnTopOfAll.userInteractionEnabled = YES;
should solve this problem. But, still if the problem persists, try,
semiTransparentViewOnTopOfAll.exclusiveTouch = YES;
do like this
button.userInteractionEnabled=NO;
by getting all buttons from view
Related
This is my first post on here and I'm very new to iPhone developing, so please bear with me.
I have an app which has a few view controllers and each view controller has a few nib files that it controls and some of the nibs have more than one view. There is a toolbar throughout the app, controlled by the root view controller.
After lot's of searching, I have got rotation working on every screen, except one. I haven't got them to load in the correct orientation, but I guess that's a different question.
In my nibs that have more than one view, I can select the autosizing options only on the original main view. On the views that I have added, which I load using insertSubview, I can select the fixed margin options, but not the width and height resizing options. I am using Xcode 4.
My 1st Question, is why I am unable to select the resizing options on the additional views?
Sorry, I had to delete the images I put in here, showing what I mean, to be able to post.
Anyway, that is not my main problem, I just want to know, out of curiosity, why I can't select the resize options. I have found a way around it in the code. In the function where I load the subview, I add [viewName setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
E.g to load the view that I have named shiftStart, I use:
- (IBAction)loadShiftStart:(id)sender {
[self clearView];
[self.view insertSubview:shiftStart atIndex:0];
[shiftStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
Now here is my problem. I have a nib file that has 3 views, view which is the main view that loads first, rotaStart, which loads as a subview when a button on the first view is pressed and shiftStart, which loads as a subview when a button on the first view is pressed. rotaStart and shiftStart are almost identical, with a title, a text block, a Yes button and a No button. The only difference is the text in the box, and which view is loaded if you click on the Yes or No buttons.
I have all the same resize and margin options selected, in Xcode, for the title, text block and buttons and as far as I can tell, the code that loads them is identical (see code below), but shiftStart rotates correctly and rotaStart does not.
- (IBAction)loadRotaStart:(id)sender {
[self clearView];
[self.view insertSubview:rotaStart atIndex:0];
[rotaStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
- (IBAction)loadShiftStart:(id)sender {
[self clearView];
[self.view insertSubview:shiftStart atIndex:0];
[shiftStart setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
}
Can anyone tell me why rotaStart is not rotating, when the phone is changed to landscape please?
Sorry this explanation has got a bit long winded. I'm not sure how else to explain it.
Thanks
For anyone else looking at this, with a similar problem, #longball solved it for me. Somehow I had managed to add a second view over the top of the base view, complete with Labels & Buttons. Deleting the extra view fixed the problem.
I set an image as a background for my view but when I add buttons, it doesn`t appear, the image hides the buttons. Can you help me please :)
Although the answer Jonathan above is perfect, but as a reference you can use this thread as another approach to handle all the placements of the views and buttons.
So you have a UIView which contains a UIImageView (the background image) and some UIButtons?
When you add the UIButtons in code, do the following for each button:
[self.view bringSubviewToFront:aButton];
Did you actually put the buttons inside the view in the view hierarchy? They might just be behind it.
I know this has been talked about a lot. I think I've gone thru every question on this site, and still have not been able to get this working.
I'm new to developing but I have a good sense of what's going on with all of my code. I definitely don't have a lot of experience though, this is my first iPhone app.
I'm making a data entry field that is comprised of multiple UITextFields within a UIScrollView. I'll avoid explaining the other details for now, as it seems its a very basic problem. Without a scrollview, the textfields work perfectly. I can touch the textfield and the keyboard or picker view show up appropriately. When I add the textfields to a scrollview, the scrollview works, but then the text fields don't receive my touches.
Here's the key: When 'User Interaction' is ENABLED, the scrollview works but the textfield touches are NOT registered. When 'User Interaction' is DISABLED, the scrollview doesn't work, but the textfield touches ARE registered and the keyboard/picker pops up.
From the other posts I have seen people creating subclasses and overriding the touches in a separate implementation. I've seen people using custom content views (subviews?), I've seen some solutions that are now obsolete since the APIs have changed in newer versions of the SDK, and I am just completely stuck.
I will leave out my code for now, because maybe there is a solution that someone has without requiring my code. If someone needs to see my code, I will put it up. My app is being written in the 3.1.3 SDK.
If anyone has ANY information that could help, it would be so greatly appreciated.
Here is what worked for me in Xcode 4.3.3.
In the storyboard, select your scrollview. Select Attribute Inspector on the right side. Uncheck Delays Content Touches.
It sounds like you're using IB to do a lot of your UI layout. If you take a programmatic approach you could set-up the following view hierarchy which should work.
Your view controller object managing your scroll view and your text fields should have a UIScrollView object and a UIView object (in addition to any UITextField objects you need). In the loadView method of the view controller class, allocate and initalize the UIView object and add your text fields to it as subviews. At the end of the method, allocate and initalize the UIScrollView object then add the UIView to the UIScrollView as a subview.
As an example, if your UIScrollView object were called scrollView and your UIView object called mainView the following lines at the end of the view controller's loadView method would properly set up the scroll view with the main view with the text fields on it:
scrollView = [[UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] bounds] ];
scrollView.backgroundColor = [UIColor whiteColor];
scrollView.contentSize = mainView.frame.size;
[scrollView addSubview: mainView];
self.view = scrollView;
You may need to enable / disable user interaction for both the scroll view and text fields as necessary.
If possible you might best using different touch mechanisms for each process (scrolling and textfield input).
Maybe you can check the time differential between touch start and end such that you can detect the difference between a drag (scroll) and a tap (text input).
Having said that if you propagate the touches up from the textfields to the scrollview you should be fine. One thing I use is:
[myObject addTarget:self action:#selector(itemTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
which passes the object touched so you can identify it and act accordingly.
I have a UISearchBar in the table cell. All done in code (not in IB). When the search bar is activated I want to disable the table view are between the search bar and keyboard, so there is no way to touch and navigate out of this view. Cannot really get it working. Help please.
You could place a transparent UIView on top of the UITableView when the search bar is active. This would effectively disable touch events, which would now be sent to the transparent UIView and would be ignored.
As a general UI technique, if you wanted to inform the end user that the table view is no longer touchable, you could set the alpha of the UIView to 50% or the like. This would "grey out" the table view underneath.
Sorry, this is an old thread, but if one comes here searching, this works for me:
self.tableView.allowsSelection = NO;
self.tableView.scrollEnabled = NO;
1.Make UISearchBar become first responder
2. Overrider capture touch event and discard when UISearchBar become first responder
- ( UITapGestureRecognizer can help you for this case)
I have a UIButton subview inside of a UITableViewCell.
When this button is touched, the user must hold the button for about a half second for the button's image to change to the UIControlStateHighlighted image.
This means that if the user just taps the button as is usually the case, the highlighted state is never shown.
Why does this occur and how can I fix it?
I just encountered this problem and saw that this issue hadn't been closed. After screwing around for a while I found a fix for it.
Now you can fix this by turning off delaysContentTouches or unchecking the "Delays content touches" box on the tableview.
The only negative side effect is that the user won't be able to tap down on a button and initiate a scrolling gesture. However, if the user tries to scroll starting from anywhere that doesn't itself accept touches, the behavior should be the same as before.
The problem is that your UIButton is inside a UITableView. This means that the table view has to determine whether your tap is going to be a swipe or if it's just a tap intended for the button. The table view has to delay sending a message to the UIButton until it knows that the user doesn't intend to swipe and therefore scroll the view instead of pressing the button.
If you don't need a table view, get rid of the UITableView.
Up for David Hodge's answer.
I just want to add a way to remove that "only negative side effect", already described by David: if you start scrolling inside a UIcontrol in a UIScrollView with delayContentTouches=NO, scrolling doesn't work.
SOLUTION
Subclass UIScrollView (or UITableView as the original question) and override:
-(BOOL) touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
Your UIControls inside UIScrollView/UITableView will change their state immediately on tap and the scrollviews will be able to scroll even if the touch starts on some UIControl. Works like a charm.
I just change the image from within the target action method:
[sender setBackgroundImage:[UIImage imageNamed:#"highlighted-image.png"] forState:UIControlStateNormal];
It changes the background image instantly.
Edit: completely re-written following a misunderstanding of the question
One way of thinking of a UIButton is as a shorthand way of setting up an area of the screen that can respond to various instantaneous touch events the response it makes is defined by UIControl's Target-Action system for delivering messages to other objects.
UIControlEventTouchDown sounds like the one you need to respond to. It will be triggered as soon as someone touches inside your button - this is what the "Contact Info" button in SMS does.
UIButton* myButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect];
// SEt up title, frame etc
[myButton addTarget:self action:#selector(myButtonWasPressed) forControlEvents: UIControlEventTouchDown];
[myMainView addSubView:myButton];
Will send a -(void)myButtonWasPressed message to the object this code runs from (ideally you view controller). In myButtonWasPressed you can then add a new view or take any action you like. The SMS app pushes a view controller to display the contact info using a navigation controller.
If this still doesn't solve your problem, you're going to have to post some code in order to get more insight into what's going wrong.