Skip to content

Latest commit

 

History

History
325 lines (241 loc) · 10.3 KB

README-CN.md

File metadata and controls

325 lines (241 loc) · 10.3 KB

HWPanModal 👍

codebeat badge

HWPanModal 用于从底部弹出控制器(UIViewController),并用拖拽手势来关闭控制器。提供了自定义视图大小和位置,高度自定义弹出视图的各个属性。

APP中常见的从底部弹出视图,可以通过该框架快速实现,只需专注于相应的视图编写。常规热门app的UI示例:

  1. 知乎APP的查看评论
  2. 抖音的评论查看
  3. 微信,网易音乐等app弹出分享
  4. 嘀嗒出行行程进行页(地图上的浮层view效果)
  5. iOS13 默认模态(present)效果
  6. And more...

截图

Basic Blur background Keyboard handle App demo

功能

  1. 支持任意类型的 UIViewController
  2. 支持继承自 HWPanModalContentView 的view
  3. 平滑的转场动画
  4. 支持2种类型的手势dismiss视图
    1. 上下方向拖动关闭视图。
    2. 侧滑关闭视图,支持全屏侧滑。
  5. 支持为presenting VC编写自定义动画。
  6. 支持配置动画时间,动画options,弹性spring值
  7. 支持配置背景alpha,或者高斯模糊背景。注意:动态调整模糊效果仅工作于iOS9.0+。
  8. 支持显示隐藏指示器,修改圆角
  9. 自动处理键盘弹出消失事件。
  10. 自定义指示器indicator view。
  11. 事件可以穿透到下层presenting VC。
  12. 可配置presented content 阴影。

更多配置信息请参阅 HWPanModalPresentable.h 声明。

特别注意

  1. 任何情况下,内部嵌套scrollable(UIScrollView,UITableView,UIWebView,UICollectionView),如果scrollable的contentSize变化了,务必调用- (void)hw_panModalSetNeedsLayoutUpdate刷新UI!!!
  2. 如果需要弹出浮层后push到下一层,使用HWPanModalContentView或者present vc用navigation 包一层。
  3. 请仔细阅读md,编译run示例代码,95%的功能在示例中都有展示,不要什么都不看就来问问题!!!

支持UIViewController和继承自HWPanModalContentView弹出视图

从0.6.0版本后, 该框架支持使用 HWPanModalContentView 从底部弹出视图, 即实现了present ViewController同样的交互和动画。

不同点是 HWPanModalContentView 只是一个view视图, 通过添加一些动画实现了原本的功能。不像present ViewController的模式,你可以获得controller的整个生命周期,并且可以使用navigation栈来push VC。

HWPanModalContentView 目前的限制:

  • 不支持转屏。
  • 不支持屏幕边缘横向拖拽来dismiss。
  • 不支持自定义presenting VC动画。(因为是view,没有presenting VC)

适配

iOS 8.0+, support Objective-C & Swift.

安装

pod 'HWPanModal', '~> 0.9.9'

如何使用

如何从底部弹出控制器

只需要视图控制器适配 HWPanModalPresentable 协议即可. 默认情况下,不用重写适配的各个方法,如果需要自定义,请实现协议方法。

更多的自定义UI配置,请参见HWPanModalPresentable协议中每个方法的说明。

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

@end

@implementation HWBaseViewController

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

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

弹出控制器:

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

就是这么简单。

如何主动更新控制器UI

请查阅 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;
    • 注意:如果scrollable view的contentSize改变了,你必须调用改reload方法来更新UI。

自定义presenting VC动画编写

  1. Create object conforms HWPresentingViewControllerAnimatedTransitioning .

    @interface HWMyCustomAnimation : NSObject <HWPresentingViewControllerAnimatedTransitioning>
    
    @end
    
    @implementation HWMyCustomAnimation
    
    
    - (void)presentAnimateTransition:(id<HWPresentingViewControllerContextTransitioning>)transitionContext {
        NSTimeInterval duration = [transitionContext transitionDuration];
        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 transitionDuration];
        UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        // replace it.
        [UIView animateWithDuration:duration animations:^{
            toVC.view.transform = CGAffineTransformIdentity;
        }];
    }
    
    @end
  2. Overwrite below two method.

    - (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle {
        return PresentingViewControllerAnimationStyleCustom;
    }
    
    - (id<HWPresentingViewControllerAnimatedTransitioning>)customPresentingVCAnimation {
        return self.customAnimation;
    }
    
    - (HWMyCustomAnimation *)customAnimation {
        if (!_customAnimation) {
            _customAnimation = [HWMyCustomAnimation new];
        }
        return _customAnimation;
    }

自定义指示器indicator view

You just need to create your own UIView, then adopt HWPanModalIndicatorProtocol.

In your presented controller, return it:

- (nullable UIView <HWPanModalIndicatorProtocol> *)customIndicatorView {
    HWTextIndicatorView *textIndicatorView = [HWTextIndicatorView new];
    return textIndicatorView;
}

Here is HWTextIndicatorView code:

@interface HWTextIndicatorView : UIView <HWPanModalIndicatorProtocol>

@end

@interface HWTextIndicatorView ()
@property (nonatomic, strong) UILabel *stateLabel;
@end

@implementation HWTextIndicatorView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // init the _stateLabel
        [self addSubview:_stateLabel];
    }
    return self;
}


- (void)didChangeToState:(HWIndicatorState)state {
    switch (state) {
        case HWIndicatorStateNormal: {
            self.stateLabel.text = @"Please pull down to dismiss";
            self.stateLabel.textColor = [UIColor whiteColor];
        }
            break;
        case HWIndicatorStatePullDown: {
            self.stateLabel.text = @"Keep pull down to dismiss";
            self.stateLabel.textColor = [UIColor colorWithRed:1.000 green:0.200 blue:0.000 alpha:1.00];
        }
            break;
    }
}

- (CGSize)indicatorSize {
    return CGSizeMake(200, 18);
}

- (void)setupSubviews {
    self.stateLabel.frame = self.bounds;
}

@end

如何使用HWPanModalContentView

你必须继承自 HWPanModalContentView. HWPanModalContentView 适配 HWPanModalPresentable 协议,就像你可用该协议来present一样。

@interface HWSimplePanModalView : HWPanModalContentView

@end

@implementation HWSimplePanModalView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // add view and layout.
    }
    
    return self;
}

// present it.
HWSimplePanModalView *simplePanModalView = [HWSimplePanModalView new];
[simplePanModalView presentInView:nil];

例子

  1. 克隆项目
  2. 然后执行 pod install
  3. 打开 HWPanModal.xcworkspace, 选择OC或者Swift项目运行
我分别编写了纯Objective-C & Swift例子,基本涵盖了该framework的所有API使用。

Star History

Star History Chart

联系我

Heath Wang yishu.jay@gmail.com

WX

License

HWPanModal is released under a MIT License. See LICENSE file for details.