Question

I'm trying to achieve the following effect. I have a view which can be in two different states - collapsed and expanded). See screenshots for what I have in mind:

Collapsed Expanded

Transition between these states should be triggered by panning gesture - user panned down view gets expanded, user panned up - view gets collapsed.

I can achieve this by implementing custom gesture recognizer in the init section of my view subclass:

UIPanGestureRecognizer* recognizer = [[UIPanGestureRecognizer alloc] initWithTarget: self action: @selector(panned:)];
recognizer.delegate = self;
[self addGestureRecognizer: recognizer];

And then detecting proper vertical pan gesture:

- (void)panned:(UIPanGestureRecognizer*)gestureRecognizer
{
    static CGPoint lastPoint;
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        lastPoint = [gestureRecognizer locationInView: self];
        return;
    }

    if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        if (p.y > lastPoint.y && self.expanded == NO) {
            [self toggle];
        }
        else if (p.y < lastPoint.y && self.expanded == YES)
        {
            [self toggle];
        }
    }
}

Then based on self.expanded property I layout subviews and change frame accordingly. Everything works more or less ok. The only issue I have is - I'd like to show transition between two states as user panning his finger - so basically view should start expanding gradually back and forth (if user pans back and forth) and then come to the expanded state when gesture is complete.

What's the easiest way to do this?

Was it helpful?

Solution

What I would do is devise an animation between the collapsed state and the expanded state. (This might involve changing one view over time, or fading / moving between two different views, one in the collapsed state and the other in the expanded state.) Now drive the animation in accordance with the gesture, as I explain here:

https://stackoverflow.com/a/22677298/341994

Basically, you attach the animation to a layer, with its speed set to 0 so that nothing actually happens. Then you track the gesture and keep changing the timeOffset of the layer to change the "frame" of the animation to match.

(One can't help observing, in this connection, that this is what is already done for you by a custom transition animation - i.e., a transition between the views of two view controllers where you add your own interactive animation. So, if you are iOS 7 only, it might be simplest to actually use a custom transition animation. That actually is how the weekly-monthly transition in the Calendar app is achieved, which you so appositely mention in a comment - it's just a push/pop transition with a custom interaction animation.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top