UIbutton taking time to receive down event in a UISCrollView on iOS5 - ios

I have the following hierarchy:
- UIView 1
- UIScrollView 2
- UIView 3
- UIView 4
- UIButton 5
My problem is that the touch down on the UIButton requires me to press for what seems a long time (like a second) to be registered by the UIButton.
The way this hierarchy is created : UIView1 is loaded from a nib file with 2 and 3 embedded but 4 is created from another nib file, first placed in one view not depicted here and then brought in 3 using addsubview. (I don't know if this is relevant).
Does somebody have any idea on how to fix this delay ? The problem appears on my 4s with ios5.1 and not in the simulator with iOS 6.

Try to set UIScrollView delaysContentTouches property to NO.
OR
Try using [button performSelector:#selector(buttonClickMethod:) afterDelay:0.0];

#interface CustomScrollView : UIScrollView {
}
#end
#implementation CustomScrollView
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
}
return self;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview] touchesEnded:touches withEvent:event];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self superview] touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[[self superview] touchesMoved:touches withEvent:event];
}
- (void)dealloc {
[super dealloc];
}
#end
Use customscrollview Instead of uiscrollview

Related

How To Add One UIGestureRecognizer to All UITextView without blocking textView touches

How To Add One UIGestureRecognizer to All UITextView without blocking textView touches..
i want to call a method when any one touch any UITextView. pls any one give me ans.
<UITextFieldDelegate>
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
Just use UITextFieldDelegate methods or add a UIView under the UITextField and add gesture recognizer to UIView
first u must add uitextfield delegate
<UITextFieldDelegate>
then use that method
(BOOL)textFieldShouldBeginEditing:(UITextField *) textField
Try like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touchesBegan");
}
Then you Handle following method in above action
[super touchesBegan:touches withEvent:event];
Your total solution is Like this this way:
#import "YourTextView.h"
#implementation YourTextView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
NSLog(#"touchesBegan");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touchesEnded");
[self.nextResponder touchesEnded: touches withEvent:event];
NSLog(#"touchesEnded");
[super touchesEnded:touches withEvent:event];
NSLog(#"touchesEnded");
}
I hope this is helpful for you.. :)
use this code this is delegate
<UITextFieldDelegate>
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField

duplicate/mirror touch events from uiview to uiscrollview

i have a uiwebview and an uiview next to each other everone taking 50% of the screen width.
i can smoothly scroll the uiwebview - and i want to be able that if i scroll up/down on the uiview - that the uiwebview scrolls in the given direction.
already subclassed uiview - and trie'd to send the touchesEnded... events to the webview.scrollview.
.h
#interface UIViewScrollDispatcher : UIView
#property(nonatomic, assign) id scroller;
.m
#implementation UIViewScrollDispatcher
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self.scroller touchesCancelled:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self.scroller touchesEnded:touches withEvent:event];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.scroller touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"TOUCHHHH %#", self.scroller);
[self.scroller touchesMoved:touches withEvent:event];
}
using it like this:
UIViewScrollDispatcher * rightarea = [[UIViewScrollDispatcher alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
rightarea.backgroundColor=[UIColor redColor];
rightarea.scroller=self.webView.scrollView;
tried it with self.webView and self.webView.scrollView
doesn't work - any help?
btw: the NSLog inside the touchesMoved gets called
regards
ok - did it with uiscrollview subclass and sync the .contentOffset and .contentSize

Subclass of UIButton connecting to IBAction of parent View Controller using Interface Builder?

Disclaimer: I'm new to Interface Builder, so it's possible I'm using it entirely incorrectly.
I've created a NavigationViewController, attached two ViewControllers to it my Storyboard, and added (dragged) a UIButton onto the first VC.
I then created a navigation segue on the UIButton that navigates between the two VCs. This works as expected.
Where things fall apart, is when I try to use a custom subclass of UIButton that I created: the segue is never fired.
In my UIButton's property inspector, I set the Custom Class to my custom class name.
I added a couple of user defined runtime attributes to the UIButton.
The UIButton header looks like this:
#import <UIKit/UIKit.h>
#interface RSButton : UIButton
#property (nonatomic) CGFloat touchAlpha;
#end
And the UIButton implementation looks like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.adjustsImageWhenHighlighted = NO;
self.highlighted = YES;
[UIView transitionWithView:self
duration:0.04
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
if (self.touchAlpha && self.touchAlpha < 1.0)
{
self.alpha = self.touchAlpha;
}
} completion:nil];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
self.highlighted = NO;
[self resetToDefaultState];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.highlighted = NO;
[self resetToDefaultState];
}
- (void)resetToDefaultState
{
[UIView transitionWithView:self
duration:0.12
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
if (self.alpha < 1)
{
self.alpha = 1.0;
}
} completion:nil];
}
Interestingly enough, I can see what the problem is: I've overridden the touchesBegan/touchesEnded events, and now the segue stuff isn't firing.
What I can't figure out is how to trigger the attached segue action programmatically?
performSegueWithIdentifier isn't available to run on [self], and
[self performSelector:#selector(performSegueWithIdentifier:#"segueId" sender:self)]; would suggest I need to know what the segueId is before I fire it.
In your method, call:
[super touchesBegan:touches withEvent:event]
So:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event]
//Your code
}
or:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//Your code
[super touchesBegan:touches withEvent:event]
}
Do the same in touchEnded etc.
IMPORTANT:
Remember to call the method on the superclass using super when you override important and standard methods like those.
It's the same that you do when you call init on your subclass:
- (id)init {
self = [super init];
if(self) {
//your code
}
return self;
}

Passing touch info to UIScrollView under another UIView

I have a UIScrollView under a transparant UIView. I need to transfer all pans and taps to the scroll view (which only scrolls horizontally). The regular UIView uses a subclass of UIPanGestureRecognizer to track vertical pans (Subclass found here). In the overlay view, I override the touch event methods to pass them to the UIScrollView.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[self.scrollView.panGestureRecognizer touchesBegan:touches withEvent:event];
[self.scrollView.singleTapGesture touchesBegan:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
[self.scrollView.panGestureRecognizer touchesCancelled:touches withEvent:event];
[self.scrollView.singleTapGesture touchesCancelled:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
[self.scrollView.panGestureRecognizer touchesEnded:touches withEvent:event];
[self.scrollView.singleTapGesture touchesEnded:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
[self.scrollView.panGestureRecognizer touchesMoved:touches withEvent:event];
[self.scrollView.singleTapGesture touchesMoved:touches withEvent:event];
}
The overlay view, the vertical pan works perfectly. In the UIScrollView, the taps also work perfectly. The scrolling though, not so much. The scroll view scrolls about three points, then stops (as I continue with the horizontal pan.) If I let go with a velocity, the scroll view then picks up that velocity and finishes scrolling.
What would be the possible issues causing the scroll view to stop scrolling then pick up the velocity?
From the code you posted, I assume you are not doing anything with the transparent UIView.. then why don't you just set userInteractionEnabled = NO; ??
Here's an easier solutions that worked well for me:
In the transparent UIView (let's call it OverlayView) make the width and height both 0 (so that the view is no longer technically on top of the UIScrollView) and set clipsToBounds = NO (so that the contents of OverlayView still show up on top of the UIScrollView).
self.OverlayView.clipsToBounds = NO;
CGRect frame = self.OverlayView.frame;
self.OverlayView.frame = CGRectMake(frame.origin.x, frame.origin.y, 0, 0);
Note that if OverlayView contains interactive controls (like the button above) then they will no longer work. You'll need to move it into it's own view above the UIScrollView.
#import "CustomUiView.h"
#implementation CustomUiView.h
-(BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event{
return NO;
}
#end
The view you do not want to interact.
create custom UIView class and use this custom view as your top view that return NO in pointInside method. Then the touch will go automatically underearth. In your case Your Transparent UIView will be CustomUiView subclass of UIView.

UIButton is not receiving actions behind UIScrollView

I put UIButton inside UITableViewCell in UITableView that is behind UIScrollView. I subclassed UIScrollView to forward touches to UITableView.
So method from UITableViewDelegate didSelectRow is calling properly. The problem is that UIButton inside table cell is not receiving TouchUpInside actions.
How can I solve this problem without deleting ScrollView over TableView?
EDIT:
I resolved this issue by detecting which view will receive touch. Here's the code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView *hitView = [self hitTest:[(UITouch*)[[touches allObjects] objectAtIndex:0] locationInView:self] withEvent:event];
if ([hitView isKindOfClass:[UIButton class]]) {
[(UIButton*)hitView sendActionsForControlEvents:UIControlEventTouchUpInside];
}
[super touchesBegan:touches withEvent:event];
}
If you want to enable actions for bouth objects - UIScrollView and UIButton you should to implement custom hit test mechanism for ScrollView.
In your UIScrollView subclass override - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method to make views behind ScrollView available for getting events.
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return __touchesEnabled;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
_touchesEnabled = NO;
UIWindow *window = [UIApplication sharedApplication].delegate.window;
for(UITouch *touch in touches) {
CGPoint point = [touch locationInView:self];
point = [window convertPoint:point fromView:self];
UIView *view = [window hitTest:point withEvent:event];
[view touchesBegan:touches withEvent:event];
}
_touchesEnabled = YES;
}
It works for me
Since you have added your scroll view over the UIButton, all the touch actions will not be passed to the button.
[yourScrollView setUserInteractionEnabled:NO];
This may solve your problem.

Resources