0

Are there one or two idiomatic ways to handle the kind of UI interaction described below? Perhaps a custom class is unnecessary?

I am implementing drag and drop in an iPadd app and would like to handle the case where the draggable is not released upon the droppable and the pan gesture leaves the UIView.

  • The view expands and gets a border when the draggable is over it, and it will return to its previous size and lose the border when the draggable leaves the area. There will be a noticeable delay before the down-scale animation begins.
  • It is possible the draggable will be brought back over the zone before the scale-down animation begins, suggesting the need for some kind of debouncing, i.e., something to collect the events that occur within a period of time and treat them as one event.
  • I know a large number of events are fired off during a pan gesture, and I don't want to allocate unnecessary resources (e.g., timers).

I was thinking of using a single custom timer, perhaps along these lines, but perhaps there's something much simpler for this?

Community
  • 1
  • 1
Eric Walker
  • 7,063
  • 3
  • 35
  • 38

1 Answers1

0

Following code will inflate the view with inflate-animation of 300ms whenever a finger moves over the view and will deflate the view back to normal whenever the touch is outside. No panGestureRecognizerRequired.

@interface CustomView : UIView
{
    BOOL hasExpanded;
    CGRect initialFrame;
    CGRect inflatedFrame;
}
@end

@implementation CustomView
-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        hasExpanded = NO;

        initialFrame = frame;

        CGFloat inflateIncrement = 50.0f;

        inflatedFrame = CGRectMake(self.frame.origin.x-(inflateIncrement*0.5f),
                                        self.frame.origin.y-(inflateIncrement*0.5f),
                                        self.frame.size.width+inflateIncrement,
                                        self.frame.size.height+inflateIncrement);

    }
    return self;
}


-(void)forceDeflate
{
    if (hasExpanded)
    {
        //start deflating view animation
        [UIView animateWithDuration:0.3 animations:^{
            self.frame = initialFrame;

        }];
        hasExpanded = NO;
    }
}


-(void)inflateByCheckingPoint:(CGPoint)touchPoint
{
    if(!hasExpanded)
    {
        if(CGRectContainsPoint(self.frame,touchPoint))
        {
            //start inflating view animation
            [UIView animateWithDuration:0.3 animations:^{
                self.frame = inflatedFrame;

            }];

            hasExpanded = YES;
        }

    }
    else
    {
        if(!CGRectContainsPoint(self.frame,touchPoint))
        {
            //start deflating view animation
            [UIView animateWithDuration:0.3 animations:^{
                self.frame = initialFrame;

            }];

            hasExpanded = NO;
        }
    }
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *singleTouch = [touches anyObject];
    CGPoint touchPoint = [singleTouch locationInView:self.superview];
    [self inflateByCheckingPoint:touchPoint];
}

-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch *singleTouch = [touches anyObject];
    CGPoint touchPoint = [singleTouch locationInView:self.superview];
    [self inflateByCheckingPoint:touchPoint];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self forceDeflate];
}

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self forceDeflate];
}

@end
CodenameLambda1
  • 1,299
  • 7
  • 17