I'm trying to see if a user swiped all the way from one view, label, etc. to another.
Here is my relevant CodeViewController.h :
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UILabel *swipeBegin;
#property (strong, nonatomic) IBOutlet UILabel *swipeEnd;
TextField : To display if the whole thing was successful.
SwipeBegin : The Label from which the swipe begins.
SwipeEnd : The Label where the swipe is supposed to end.ViewController.m :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if ([touch view] == swipeBegin) {
gestureStartPointTouched = YES;
}
If the swipe began at "swipeBegin" a bool value is set to YES.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if ([touch view] == swipeEnd) {
if (gestureStartPointTouched == YES) {
[TextField setText:#"Success"];
}
}
If I start swiping at "swipeBegin" the touchesBegan method is called -> works fine
The troubling part is the touchesEnded method.
if([touch view] == swipeEnd)
is false no matter what i do about it.
Does anybody have an advice ?
Thank You !SolutionEditing the touchesEnded method :
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if ([self.view hitTest:[[touches anyObject] locationInView:self.view] withEvent:event] == SwipeEnd) {
if (gestureStartPointTouched == YES) {
[TextField setText:#"Success"];
}
}
The view of the touch never changes, if it starts in swipeBegin that will always be it's view. If you want to find out where it ended use hitTest:withEvent: with the touch's end location, that will return the view you are looking for.
Related
Because some reasons, I create a UIView xib file to reuse.
How to know which UIView when I click from xib?
I create a xib file extends UIView(named with XibView).
Then I drag two UIView(leftView,rightView) in the storyboard, and set the custom class "XibView" in XCode inspector window.
When I compile the code, It will get correct result that show two UIViews.
XibView.m file part code below:
-(id) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if( self )
{
UIView *containerView = [[[UINib nibWithNibName:#"XibView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
CGRect newFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
containerView.frame = newFrame;
[self addSubview:containerView];
}
return self;
}
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"tap in xib");
......
}
But How can I know which UIView is my click?
// I add some detail description.
In the xib custom class, I will using post the notify to the uiviewcontroller and take some data when user click in xib(touchesBegan is in the xib custom class).
I have two uiview in the storyboard , these uiview will using the xib file.
so I want to know when I click which uiview, I can know which one user click.
// ------------- answer . please refer #Boyi Li answer. ---------
In the XibView.m had add the
[super touchesBegan:touches withEvent:event];
to override the touches begain method.
and add the XibView header file in the viewcontroller.
It can drag the refer to the viewcontroller.
As your said, you could assign different tag for these two views. Inside XibView, you could check self.tag == <tag>.
If you want to get specific view in parent view or controller, use viewWithTag: method. It will check hierarchy whose tag property matches the value in the tag parameter.
Update:
Create IBOutlet Reference in ViewController for left and right Views. In your controller, you have:
#property (nonatomic, weak) IBOutlet XibView *leftView;
#property (nonatomic, weak) IBOutlet XibView *rightView;`
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint leftTouchPoint = [touch locationInView:leftView];
CGPoint rightTouchPoint = [touch locationInView:rightView];
if ([self.leftView pointInside:leftTouchPoint withEvent:event]) {
// Do something for leftView
} else if ([self.rightView pointInside:rightTouchPoint withEvent:event]) {
// Do something for Right View
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
if ([touch.view isKindOfClass: UIView.class])
{
UIView *view=touch.view;
if (view==YourView1)
{
//start editing
}else
if (view==YourView2)
{
//start editing
}
}
else
{
}
}
Any idea how to do this? I have a UIImageView inside of each cell in my UITableView and I want to disable scroll when the user starts touching the UIImageView and then enable it once the user stops dragging their finger on the photo.
I just give my logic.
Add UIPanGestureRecognizer to each cell of UITableView.
UIPanGestureRecognizer* panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanFrom:)];
[cell addGestureRecognizer:panGestureRecognizer];
And in method name is handlePanFrom:
- (void)handlePanFrom:(UIPanGestureRecognizer*)recognizer
{
CGPoint translation = [recognizer translationInView:recognizer.view];
CGPoint velocity = [recognizer velocityInView:recognizer.view];
if (recognizer.state == UIGestureRecognizerStateBegan)
{
/// track began
tableView.userInteractionEnabled = NO;
}
else if (recognizer.state == UIGestureRecognizerStateChanged)
{
// track the movement
} else if (recognizer.state == UIGestureRecognizerStateEnded)
{
// final position
tableView.userInteractionEnabled = YES;
}
}
Make sure your UIIMageView must be set as a userInteractionEnabled = YES;. Because by default UIIMageView have to set userInteractionEnabled = NO;.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch.view isKindOfClass:[UIImageView class]]) {
NSLog(#"self.tableView.scrollEnabled = NO");
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if ([touch.view isKindOfClass:[UIImageView class]]) {
NSLog(#"self.tableView.scrollEnabled = YES");
}
}
There are two ways to implement this, either include UITapGestureRecognizer or UIPanGestureRecognizer to your UIImageView and set the target and action where target is your custom UITableViewCell class or include
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
methods in the UIImageView custom class and set the delegate via protocol to your custom UITableViewCell.
for UIGestureRecognizer you can check its state property UIGestureRecognizer Class Reference to know the state with the help of switch
typedef enum {
UIGestureRecognizerStatePossible,
UIGestureRecognizerStateBegan,
UIGestureRecognizerStateChanged,
UIGestureRecognizerStateEnded,
UIGestureRecognizerStateCancelled,
UIGestureRecognizerStateFailed,
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
}
Finally, by toggling the UITableView's scrollEnabled property to stop and start scrolling where UITableView is a sub class of UIScrollView
I've an UITextView into an UITableViewCell, but I can't scroll the text. When I try to scroll the textView, the tableView catch the touches.
There is any way to fix this?
PS: Subclass of UITableViewController
I'm thinking you can detect the object being touched and if it is a UITextView, then temporarily disable scrolling with UITableView:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
//detect if touch is on UITextView
if ([touch.view isKindOfClass: UITextView.class]) {
yourTableView.scrollEnabled = NO;
}
}
Don't forget to re-enable scrolling of the UITableView afterwards in touchesEnded
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
yourTableView.scrollEnabled = YES;
}
I have a very complex app with lots of stacked views which contain lots of buttons ,drawing areas and other custom touch handling . I am displaying a draggable helper view which can be on top of all the other views . I need to dismiss this view if the user taps anywhere outside the helper view . I have tried using multiple UIWindows and adding Gesture recognizers to the UIWindow .
A easy is to add a transparent button which bounds is equal the superview's bounds. And the superview insert the transparent button below your helper view.
The transparent button add a click event which can dismiss the helper view and the transparent button it self.
For example :
UIButton *transparencyButton = [[UIButton alloc] initWithFrame:superview.bounds];
transparencyButton.backgroundColor = [UIColor clearColor];
[superview insertSubview:transparencyButton belowSubview:helperView];
[transparencyButton addTarget:self action:#selector(dismissHelper:) forControlEvents:UIControlEventTouchUpInside];
and the dismissHelper: method can do this :
- (void)dismissHelper:(UIButton *)sender
{
[helperView dismiss];
sender.hidden = YES;
// or [sender removeFromSuperview]
}
You can check the view being touched by going through the touches and looking at the .view property of the touch. It reflects the view from where the view actually originates.
Assuming that you keep a reference to your view (either via an IBOutlet or otherwise) to your view called "myView" the below works.
In your .m file. The touchesBegan: function is triggered every time the user touches a finger down. We loop through the touches to see if the originating view of the touch is NOT equal to "myView". This comparison could also be done via checking the class, tag or any other property you use to identify your view. Examples given below.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches began");
UITouch *touch = [touches anyObject];
if(touch.view!=myView){
myView.hidden = YES;
}
}
Or in case of using a tag:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches began");
UITouch *touch = [touches anyObject];
if(touch.view.tag!=23){
myView.hidden = YES;
}
}
create an hittestintercept view. this can make the view below handle events like before.
#protocol HitTestInterceptViewDelegate <NSObject>
- (BOOL)interceptHitTest:(CGPoint)point withEvent:(UIEvent *)event;
#end
#interface HitTestInterceptView : UIView
#property(nonatomic, weak) id<HitTestInterceptViewDelegate> hitTestInterceptDelegate;
#end
HtiTestInterceptView.m
#import "HitTestInterceptView.h"
#implementation HitTestInterceptView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if ([_hitTestInterceptDelegate interceptHitTest:point withEvent:event] == NO) {
return [super hitTest:point withEvent:event];
}
return nil;
}
#end
then use it in the toast view
- (void)dismissIfTouchOutsideInView:(UIView *)view {
if (_interceptView != nil) return;
_interceptView = [[HitTestInterceptView alloc] initWithFrame:view.bounds];
_interceptView.backgroundColor = [UIColor clearColor];
_interceptView.hitTestInterceptDelegate = self;
[view insertSubview:_interceptView belowSubview:self];
}
- (BOOL)interceptHitTest:(CGPoint)point withEvent:(UIEvent *)event {
dispatch_async(dispatch_get_main_queue(), ^{
// [self dismiss];
});
return YES;
}
What's the Xcode code for this pseudocode?
if ([Any UIPickerView in my ViewController isTouched]) {
[AnyUIView setHidden:NO];
}
if ([Any UIPickerView in my ViewController is__NOT__Touched__Anymore__]) {
[AnyUIView setHidden:YES];
}
Tried it with the -(void)touchesBeganmethod, it detects the touches but I was not able to make it object-specific. Thanks
P.S. I want to display a hint on the display while the UIPickerViewis touched.
This is just from the top of my head...... but you should be able to get the idea...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
if ([touch.view isKindOfClass: UIPickerView.class]) {
//your touch was in a uipickerview ... do whatever you have to do
}
}
..and do the same with touchesEnded:withEvent: