HWPanModal is used to present controller and drag to dismiss.



  1. Supports any type of UIViewController
  2. Seamless transition between modal and content
  3. Support two kinds of GestureRecognizer
    1. UIPanGestureRecognizer, direction is UP & Down.
    2. UIScreenEdgePanGestureRecognizer, you can swipe on screen edge to dismiss controller.
  4. Support write your own animation for presenting VC.


iOS 8.0+, support Objective-C & Swift.


KVOController - facebook

Because Objective-C KVO is hard to use, so I use KVOController = =



pod 'HWPanModal', '~>'

How to use

How to present from bottom

Your UIViewController need to conform HWPanModalPresentable. If you use default, nothing more will be written.

#import <HWPanModal/HWPanModal.h>
@interface HWBaseViewController () <HWPanModalPresentable>


@implementation HWBaseViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

#pragma mark - HWPanModalPresentable
- (PanModalHeight)longFormHeight {
    return PanModalHeightMake(PanModalHeightTypeMaxTopInset, 44);

Where you need to present this Controller.

#import <HWPanModal/HWPanModal.h>
[self presentPanModal:[HWBaseViewController new]];

yeah! Easy.

Change state, scrollView contentOffset, reload layout

When You present you Controller, you can change the UI.
Refer to UIViewController+Presentation.h.

  • Change the state between short and long form. call - (void)hw_panModalTransitionTo:(PresentationState)state;
  • Change ScrollView ContentOffset. call - (void)hw_panModalSetContentOffset:(CGPoint)offset;
  • Reload layout. call - (void)hw_panModalSetNeedsLayoutUpdate;

Custom Presenting VC Animation

Some guys want to animate Presenting VC when present/dismiss.

  1. Create object conforms HWPresentingViewControllerAnimatedTransitioning .

    @interface HWMyCustomAnimation : NSObject <HWPresentingViewControllerAnimatedTransitioning>
    @implementation HWMyCustomAnimation
    - (void)presentAnimateTransition:(id<HWPresentingViewControllerContextTransitioning>)transitionContext {
        NSTimeInterval duration = [transitionContext mainTransitionDuration];
        UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        // replace it.
        [UIView animateWithDuration:duration delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            fromVC.view.transform = CGAffineTransformMakeScale(0.95, 0.95);
        } completion:^(BOOL finished) {
    - (void)dismissAnimateTransition:(id<HWPresentingViewControllerContextTransitioning>)transitionContext {
        NSTimeInterval duration = [transitionContext mainTransitionDuration];
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        // replace it.
        [UIView animateWithDuration:duration animations:^{
            toVC.view.transform = CGAffineTransformIdentity;
  2. Overwrite below two method.

    - (BOOL)shouldAnimatePresentingVC {
        return YES;
    - (id<HWPresentingViewControllerAnimatedTransitioning>)customPresentingVCAnimation {
        return self.customAnimation;
    - (HWMyCustomAnimation *)customAnimation {
        if (!_customAnimation) {
            _customAnimation = [HWMyCustomAnimation new];
        return _customAnimation;


  1. Clone this git.
  2. open the terminal´╝î go to the Example Folder.
  3. pod install --verbose
  4. Double click HWPanModal.xcworkspace, and run.