👍
HWPanModal
HWPanModal 用于显示控制器并进行拖动以取消显示。与 iOS13 默认的 Present Modal 样式相似。
受 PanModal 的启发,谢谢。
我用于弹出控制器的另一个项目:HWPopController
特别感谢
特别感谢 JetBrains!我使用 AppCode IDE 来开发我的开源项目。
截图
索引
特性
- 支持任何类型的
UIViewController
进行展示。 - 支持展示继承自
HWPanModalContentView
的 View。 - 模态和内容之间无缝转换。
- 支持两种消失手势识别器的交互
- 向上和向下滑动手势
- 向右滑动手势,您可以在屏幕边缘滑动以消失控制器。
- 支持编写自己的动画以展示 VC。
- 支持配置动画
Duration
、AnimationOptions
和springDamping
。 - 支持配置背景透明度或
blur
背景。注意:动态更改模糊效果仅支持 iOS 9.0+。 - 显示/隐藏角标、指示器。
- 自动处理 UIKeyboard 的显示/隐藏。
- 高自定义指示器视图。
- 触摸事件可以传入展示 VC。
- 配置展示视图的阴影样式。
更多配置请参见 HWPanModalPresentable.h 的声明。
UIViewController 和 HWPanModalContentView 用于展示的区别是什么?
从版本 0.6.0 开始,此框架支持使用 HWPanModalContentView
从底部进行展示,这意味着我们可以将(继承自 HWPanModalContentView
的)子视图添加到您想要显示的目标视图中。
区别在于 HWPanModalContentView
只是一个 View,并且支持一些动画,与展示 ViewController 不同,您将获得 ViewController 生命周期,和导航栈。
HWPanModalContentView
的限制
- 当前不支持屏幕旋转。
- 不支持边缘水平滑动以消失。
- 不支持自定义展示ViewController动画。(对于视图没有展示ViewController)。
待办事项
- 处理键盘显示和消失。
- 高自定义指示器视图。
- 边缘交互式消失可以在全屏上使用并可配置与左侧边缘的距离。
- 触摸事件可以响应显示VC,正在处理。
- 移除已显示的视图容器视图,使其可以直接使用。
兼容性
iOS 8.0+,支持Objective-C & Swift。
安装
CocoaPods
pod 'HWPanModal', '~> 0.9.4'
如何使用
如何从底部呈现UIViewController
你的UIViewController需要遵守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]];
是的!很简单。
更改状态、scrollView内容偏移、重新加载布局。重要!
展示控制器时,您可以更改UI。请查阅UIViewController+Presentation.h
。
- 在简短形式和长形式之间更改状态。调用
- (void)hw_panModalTransitionTo:(PresentationState)state;
- 更改ScrollView内容偏移。调用
- (void)hw_panModalSetContentOffset:(CGPoint)offset;
- 重新加载布局。调用
- (void)hw_panModalSetNeedsLayoutUpdate;
- 注意:当您的可滚动内容尺寸改变时,您必须重新加载布局。
自定义Presenting VC动画
有些人想在展示/消失时对Presenting VC进行动画处理。
-
创建一个遵守
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 { // no need for using animating block. UIViewController *toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey]; toVC.view.transform = CGAffineTransformIdentity; } @end
-
重写以下两个方法。
- (PresentingViewControllerAnimationStyle)presentingVCAnimationStyle { return PresentingViewControllerAnimationStyleCustom; } - (id<HWPresentingViewControllerAnimatedTransitioning>)customPresentingVCAnimation { return self.customAnimation; } - (HWMyCustomAnimation *)customAnimation { if (!_customAnimation) { _customAnimation = [HWMyCustomAnimation new]; } return _customAnimation; }
自定义您自己的指示器视图
您只需要创建您自己的UIView,然后遵守HWPanModalIndicatorProtocol
。
在您的展示控制器中,返回它
- (nullable UIView <HWPanModalIndicatorProtocol> *)customIndicatorView {
HWTextIndicatorView *textIndicatorView = [HWTextIndicatorView new];
return textIndicatorView;
}
下面是HWTextIndicatorView
的代码
@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
类似于使用 UIViewController 的方式实现了 HWPanModalPresentable
。
@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];
示例
- 克隆此 Git。
- 打开终端,运行
pod install
- 双击 HWPanModal.xcworkspace,并选择要运行的目标。
Objective-C
和 Swift
示例。
我为大多数框架功能编写了 纯 联系我
微信
变更日志
许可
HWPanModal 采用 MIT 许可协议发布。详细信息请参见 LICENSE 文件。