Steps up to 5 contain the creation of the subview itself, but if you are only interested on the dragging events read from step five, which is about the panGestureRecognizer.
Create a custom UIView, I have also created a delegate protocol to inform the viewController when an action occurs on the subview. Depending on how much complicated your subview will be, you may want to create a xib file with the same name for that. Let's call it filterView from now on.
Create two methods like "hide" and "show" on the filterView. If you do not want to have a button (namely the small button with the arrow, I ll call it dropdownButton) to close and open the filterView, you may skip this step, but I strongly recommend to implement them. What you have to do is to animate filterView.frame.origin.y to
If requested I can also send code for that animations.
3.
Open the xib file for the UIViewController and add a UIView, so that only its dropdown button will be visible. Click the view and change its class to filterView using the rightmost pane in the interface builder. At this step you should be able to see your filtersView's tip on the bottom of the page if you did everything correctly. If not, the filterView.xib file is probably not correctly connected to filterView source code files.
4
.
Import the FilterView in the ViewController and connect as IBOutlet & synthetize it. Implement the delegate protocol if you have written one. If you have buttons on the filterView, you will need it later on. The delegate protocol should include optional messages like
-(void) featuresButtonTappedOnFilterView: (FilterView *) filterView;
and in the implementation you should do what you have to do in the viewController, like opening another viewController.
5
. On the viewControllers xib file create a panGestureRecognizer and add it to your filterView. PanGestureRecognizer is a gestureRecognizer which will handle the dragging events. At first the whole filterView will be able to dragged around by clicking any point on it, we will get to that later. Connect the gestureRecognizer as IBOutlet and create an IBAction (preferably with a better name) like:
-(IBAction)_panRecogPanned:(id)sender;
In the viewDidLoad method of the ViewController dont forget to set the delegate as:
[_panRecog setDelegate:self];
6
. Implement other states for more power. but stateChanged will be sufficient at first.
- (IBAction)_panRecogPanned:(id)sender {
switch ([(UIPanGestureRecognizer*)sender state]) {
case UIGestureRecognizerStateBegan: { } break;
case UIGestureRecognizerStateChanged: {
if ( [((UIPanGestureRecognizer *)sender) locationInView:_filterView].y > dropDownButton.frame.height )
return; // Only drag if the user's finger is on the button
CGPoint translation = [_panRecog translationInView:filterView];
//Note that we are omitting translation.x, otherwise the filterView will be able to move horizontally as well. Also note that that MIN and MAX were written for a subview which slides down from the top, they wont work on your subview.
CGRect newFrame = _panRecog.view.frame;
//newFrame.origin.y = MIN (_panRecog.view.frame.origin.y + translation.y, FILTER_OPEN_ORIGIN_Y);
//newFrame.origin.y = MAX (newFrame.origin.y, FILTER_INITIAL_ORIGIN_Y);
newFrame.origin.y = _panRecog.view.frame.origin.y + translation.y;
_panRecog.view.frame = newFrame;
[_panRecog setTranslation:CGPointMake(0, 0) inView:self.view];
} break;
//Remember the optional step number 2? We will use hide/ show methods now:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
//CGPoint velocity = [_panRecog velocityInView:_panRecog.view];
//Bonus points for using velocity when deciding what to do when if the user lifts his finger
BOOL open;
/*
if (velocity.y < -600.0) {
open = NO;
}
else if (velocity.y >= 600.0) {
open = YES;
} else
*/
if ( _panRecog.view.frame.origin.y > (FILTER_OPEN_ORIGIN_Y + FILTER_INITIAL_ORIGIN_Y) / 2 ) {
open = YES;
}
else {
open = NO;
}
if (open == YES) {
[_filterView show];
}
else {
[_filterView hide];
}
} break;
default:
break;
}
}
Note: My filter view was on the top of the page instead of the bottom, as it is the subview will move out of the page borders. Comment out the MAX and MIN statements to fix that, I am to lazy to write them by myself. The code is modified after copy&paste, it may (and probably will) contain typos.