MZFormSheetController 3.1.3

MZFormSheetController 3.1.3

测试已测试
语言语言 Obj-CObjective C
版权 MIT
发布上次发布2015年12月

Michal Zaborowski 维护。



  • Michał Zaborowski

MZFormSheetController v3

MZFormSheetController 已被重新编写并被 MZFormSheetPresentationController 所取代,后者基于新的 iOS 8 模态显示 API。如果您想支持 iOS8,您仍然可以使用 MZFormSheetController,但如果您的部署目标设置为 iOS8,我建议您使用 MZFormSheetPresentationController,我已经放弃了支持这个项目,转而支持 MZFormSheetPresentationController。MZFormSheetPresentationController 不使用任何花招将表单页作为 UIWindow 显示,它使用原生 modalPresentationStyle UIModalPresentationOverFullScreen,并使用原生的 UIVisualEffect 视图来创建模糊效果。

MZFormSheetPresentationController 包含 Swift 和 Objective-C 的示例项目。

MZFormSheetController

MZFormSheetController 为原生 iOS UIModalPresentationFormSheet 提供了一种替代方案,添加了对 iPhone 以及设置控制器大小和显示表单页的机会。

如何使用

让我们从一个简单示例开始

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"nav"];

// present form sheet with view controller
[self mz_presentFormSheetController:vc animated:YES completionHandler:^(MZFormSheetController *formSheetController) {
   //do sth
}];

这将在表单页容器内显示视图控制器。

如果您想关闭表单页控制器,您可以使用 UIViewController 类别的访问 formSheetController

[self mz_dismissFormSheetControllerAnimated:YES completionHandler:^(MZFormSheetController *formSheetController) {
    // do sth
}];

传递数据

formSheet.willPresentCompletionHandler = ^(UIViewController *presentedFSViewController) {
    // Passing data
    UINavigationController *navController = (UINavigationController *)presentedFSViewController;
    navController.topViewController.title = @"PASSING DATA";
};

触摸透明背景

如果您想访问位于 MZFormSheet 之下的控制器,可以将背景窗口设置为触摸透明。

MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithViewController:vc];

formSheet.formSheetWindow.transparentTouchEnabled = YES;

[formSheet presentAnimated:YES completionHandler:^(UIViewController *presentedFSViewController) {

}];

模糊背景效果

可以显示模糊背景,您可以设置 MZFormSheetWindow 的外观,或者直接设置到窗口。

[[MZFormSheetBackgroundWindow appearance] setBackgroundBlurEffect:YES];
[[MZFormSheetBackgroundWindow appearance] setBlurRadius:5.0];
[[MZFormSheetBackgroundWindow appearance] setBackgroundColor:[UIColor clearColor]];
[[MZFormSheetController sharedBackgroundWindow] setBackgroundBlurEffect:YES];
[[MZFormSheetController sharedBackgroundWindow] setBlurRadius:5.0];
[[MZFormSheetController sharedBackgroundWindow] setBackgroundColor:[UIColor clearColor]];

转场

MZFormSheetController 有预定义的转场效果。

typedef NS_ENUM(NSInteger, MZFormSheetTransitionStyle) {
    MZFormSheetTransitionStyleSlideFromTop = 0,
    MZFormSheetTransitionStyleSlideFromBottom,
    MZFormSheetTransitionStyleSlideFromLeft,
    MZFormSheetTransitionStyleSlideFromRight,
    MZFormSheetTransitionStyleSlideAndBounceFromLeft,
    MZFormSheetTransitionStyleSlideAndBounceFromRight,
    MZFormSheetTransitionStyleFade,
    MZFormSheetTransitionStyleBounce,
    MZFormSheetTransitionStyleDropDown,
    MZFormSheetTransitionStyleCustom,
    MZFormSheetTransitionStyleNone,
};

您可以通过继承 MZTransition 来创建自己的转场效果。

/**
 *  Register custom transition animation style.
 *  You need to setup transitionStyle to MZFormSheetTransitionStyleCustom.
 *
 *  @param transitionClass Custom transition class.
 *  @param transitionStyle The transition style to use when presenting the receiver.
 */
+ (void)registerTransitionClass:(Class)transitionClass forTransitionStyle:(MZFormSheetTransitionStyle)transitionStyle;

+ (Class)classForTransitionStyle:(MZFormSheetTransitionStyle)transitionStyle;

@protocol MZFormSheetControllerTransition <NSObject>
@required
/**
 Subclasses must implement to add custom transition animation.
 When animation is finished you must call super method or completionHandler to keep view life cycle.
 */
- (void)entryFormSheetControllerTransition:(MZFormSheetController *)formSheetController completionHandler:(MZTransitionCompletionHandler)completionHandler;
- (void)exitFormSheetControllerTransition:(MZFormSheetController *)formSheetController completionHandler:(MZTransitionCompletionHandler)completionHandler;

@end

@interface MZCustomTransition : MZTransition <MZFormSheetControllerTransition>
@end

- (void)entryFormSheetControllerTransition:(MZFormSheetController *)formSheetController completionHandler:(MZTransitionCompletionHandler)completionHandler
{
    // It is very important to use self.view.bounds not self.view.frame !!!
    // When you rotate your device, the device is not changing its screen size.
    // It is staying the same, however the view is changing. So this is why you would want to use bounds.

    CGRect formSheetRect = self.presentedFSViewController.view.frame;
    CGRect originalFormSheetRect = formSheetRect;
    originalFormSheetRect.origin.x = self.view.bounds.size.width - formSheetRect.size.width - 10;
    formSheetRect.origin.x = self.view.bounds.size.width;
    self.presentedFSViewController.view.frame = formSheetRect;
    [UIView animateWithDuration:MZFormSheetControllerDefaultAnimationDuration
                     animations:^{
                         self.presentedFSViewController.view.frame = originalFormSheetRect;
                     }
                     completion:^(BOOL finished) {
                         if (completionHandler) {
                             completionHandler();
                         }
                     }];
}
- (void)exitFormSheetControllerTransition:(MZFormSheetController *)formSheetController completionHandler:(MZTransitionCompletionHandler)completionHandler
{
    CGRect formSheetRect = self.presentedFSViewController.view.frame;
    formSheetRect.origin.x = self.view.bounds.size.width;
    [UIView animateWithDuration:MZFormSheetControllerDefaultAnimationDuration
                          delay:0
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{
                         self.presentedFSViewController.view.frame = formSheetRect;
                     }
                     completion:^(BOOL finished) {
                         if (completionHandler) {
                             completionHandler();
                         }
                     }];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [MZFormSheetController registerTransitionClass:[MZCustomTransition class] forTransitionStyle:MZFormSheetTransitionStyleCustom];

    self.transitionStyle = MZFormSheetTransitionStyleCustom;
    self.presentedFSViewController.view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
}

全屏模态视图控制器

可以全屏显示模态视图控制器在表单之上。

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"nav"];
UIViewController *modal = [self.storyboard instantiateViewControllerWithIdentifier:@"modal"];

[self mz_presentFormSheetWithViewController:vc animated:YES transitionStyle:MZFormSheetTransitionStyleSlideAndBounceFromLeft completionHandler:^(MZFormSheetController *formSheetController) {

    [formSheetController presentViewController:modal animated:YES completion:^{

    }];

}];

自定义组合视图控制器

您可以在故事板上轻松创建自己的自定义组合视图控制器,并展示它们。

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"facebook"];

MZFormSheetController *formSheet = [[MZFormSheetController alloc] initWithViewController:vc];
formSheet.shouldDismissOnBackgroundViewTap = YES;
formSheet.transitionStyle = MZFormSheetTransitionStyleSlideFromBottom;
formSheet.cornerRadius = 8.0;
formSheet.portraitTopInset = 6.0;
formSheet.landscapeTopInset = 6.0;
formSheet.presentedFormSheetSize = CGSizeMake(320, 200);


formSheet.willPresentCompletionHandler = ^(UIViewController *presentedFSViewController){
    presentedFSViewController.view.autoresizingMask = presentedFSViewController.view.autoresizingMask | UIViewAutoresizingFlexibleWidth;
};

[formSheet presentAnimated:YES completionHandler:^(UIViewController *presentedFSViewController) {

}];

or

[self presentFormSheetController:formSheet animated:YES completionHandler:^(MZFormSheetController *formSheetController) {

}];

外观

MZFormSheetController 支持外观代理。

id appearance = [MZFormSheetController appearance];

[appearance setBackgroundOpacity:0.2];
[appearance setCornerRadius:4];
[appearance setShadowOpacity:0.4];
@interface MZFormSheetBackgroundWindow : UIWindow <MZAppearance>

/**
 The background color of the background view.
 After last form sheet dismiss, backgroundColor will change to default.
 If you want to set it permanently to another color use appearance proxy on MZFormSheetBackgroundWindow.
 By default, this is a black at with a 0.5 alpha component
 */
@property (nonatomic, strong) UIColor *backgroundColor MZ_APPEARANCE_SELECTOR;

/**
 The background image of the background view, it is setter for backgroundImageView and can be set by MZAppearance proxy.
 After last form sheet dismiss, backgroundImage will change to default.
 If you want to set it permanently to another color use appearance proxy on MZFormSheetBackgroundWindow.
 By default, this is nil
 */
@property (nonatomic, strong) UIImage *backgroundImage MZ_APPEARANCE_SELECTOR;

/**
 The background image view, if you want to set backgroundImage use backgroundImage property.
 */
@property (nonatomic, strong, readonly) UIImageView *backgroundImageView;

/*
 Apply background blur effect
 By default, this is NO
 */
@property (nonatomic, assign) BOOL backgroundBlurEffect MZ_APPEARANCE_SELECTOR;

/*
 Specifies the blur radius used to render the blur background view
 By default, this is 2.0
 */
@property (nonatomic, assign) CGFloat blurRadius MZ_APPEARANCE_SELECTOR;

/*
 Specifies the blur tint color used to render the blur background view
 By default, this is nil
 */
@property (nonatomic, strong) UIColor *blurTintColor MZ_APPEARANCE_SELECTOR;

/*
 Specifies the blur saturation used to render the blur background view
 By default, this is 1.0
 */
@property (nonatomic, assign) CGFloat blurSaturation MZ_APPEARANCE_SELECTOR;

/*
 Specifies the blur mask image used to render the blur background view
 By default, this is nil
 */
@property (nonatomic, strong) UIImage *blurMaskImage MZ_APPEARANCE_SELECTOR;

/*
 Asynchronously recompute the display of background blur.
 Recommended to use if you expect interface orientation or some dynamic animations belof form sheet
 */
@property (nonatomic, assign) BOOL dynamicBlur MZ_APPEARANCE_SELECTOR;

/*
 Specifies how often the blur background refresh.
 Works only if dynamicBlur is set to YES.
 By default, this is 0
 */
@property (nonatomic, assign) CGFloat dynamicBlurInterval MZ_APPEARANCE_SELECTOR;

/*
 All of the interface orientations that the background image view supports.
 By default, this is UIInterfaceOrientationMaskAll
 */
@property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations MZ_APPEARANCE_SELECTOR;
@end
typedef NS_ENUM(NSInteger, MZFormSheetWhenKeyboardAppears) {
  MZFormSheetWhenKeyboardAppearsDoNothing = 0,
  MZFormSheetWhenKeyboardAppearsCenterVertically,
  MZFormSheetWhenKeyboardAppearsMoveToTop,
  MZFormSheetWhenKeyboardAppearsMoveToTopInset,
};

/**
 Returns the window that is displayed below form sheet controller
 */
+ (MZFormSheetBackgroundWindow *)sharedBackgroundWindow;

/**
 Distance that the presented form sheet view is inset from the status bar in landscape orientation.
 By default, this is 6.0
 */
@property (nonatomic, assign) CGFloat landscapeTopInset MZ_APPEARANCE_SELECTOR;

/**
 Distance that the presented form sheet view is inset from the status bar in portrait orientation.
 By default, this is 66.0
 */
@property (nonatomic, assign) CGFloat portraitTopInset MZ_APPEARANCE_SELECTOR;

/**
 The radius to use when drawing rounded corners for the layer’s presented form sheet view background.
 By default, this is 6.0
 */
@property (nonatomic, assign) CGFloat cornerRadius MZ_APPEARANCE_SELECTOR;

/**
 The blur radius (in points) used to render the layer’s shadow.
 By default, this is 6.0
 */
@property (nonatomic, assign) CGFloat shadowRadius MZ_APPEARANCE_SELECTOR;

/**
 The opacity of the layer’s shadow.
 By default, this is 0.5
 */
@property (nonatomic, assign) CGFloat shadowOpacity MZ_APPEARANCE_SELECTOR;

/**
 Size for presented form sheet controller
 By default, this is CGSizeMake(284.0,284.0)
 */
@property (nonatomic, assign) CGSize presentedFormSheetSize MZ_APPEARANCE_SELECTOR;

/**
 Center form sheet vertically.
 By default, this is NO
 */
@property (nonatomic, assign) BOOL shouldCenterVertically MZ_APPEARANCE_SELECTOR;

/**
 The movement style to use when the keyboard appears.
 By default, this is MZFormSheetWhenKeyboardAppearsMoveToTop.
 */
@property (nonatomic, assign) MZFormSheetWhenKeyboardAppears movementWhenKeyboardAppears MZ_APPEARANCE_SELECTOR;

完成块

/**
 The handler to call when presented form sheet is before entry transition and its view will show on window.
 */
@property (nonatomic, copy) MZFormSheetCompletionHandler willPresentCompletionHandler;

/**
 The handler to call when presented form sheet will be dismiss, this is called before out transition animation.
 */
@property (nonatomic, copy) MZFormSheetCompletionHandler willDismissCompletionHandler;

/**
 The handler to call when presented form sheet is after entry transition animation.
 */
@property (nonatomic, copy) MZFormSheetCompletionHandler didPresentCompletionHandler;

/**
 The handler to call when presented form sheet is after dismiss.
 */
@property (nonatomic, copy) MZFormSheetCompletionHandler didDismissCompletionHandler;

通知

/**
 Notifications are posted right after completion handlers

 @see willPresentCompletionHandler
 @see willDismissCompletionHandler
 @see didPresentCompletionHandler
 @see didDismissCompletionHandler
 */

extern NSString *const MZFormSheetWillPresentNotification;
extern NSString *const MZFormSheetWillDismissNotification;
extern NSString *const MZFormSheetDidPresentNotification;
extern NSString *const MZFormSheetDidDismissNotification;

支持的界面方向

MZFormSheetController 支持所有界面方向。如果您想在方向改变时调整表单控制器的大小,可以使用 autoresizeMask 属性。

您可以使用以下代码来操作界面方向

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    NSUInteger orientations = UIInterfaceOrientationMaskAll;

    if ([MZFormSheetController formSheetControllersStack] > 0) {
        MZFormSheetController *viewController = [[MZFormSheetController formSheetControllersStack] lastObject];
        return [viewController.presentedFSViewController supportedInterfaceOrientations];
    }

    return orientations;
}

PreferredStatusBarStyle (iOS7)

显示的视图控制器或 UINavigationController 的 topViewController 用于确定状态栏样式。如果您不希望这种行为,可以子类化 MZFormSheetController。

- (UIViewController *)childViewControllerForStatusBarStyle
{
    if ([self.presentedFSViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController *navigationController = (UINavigationController *)self.presentedFSViewController;
        return [navigationController.topViewController mz_childTargetViewControllerForStatusBarStyle];
    }

    return [self.presentedFSViewController mz_childTargetViewControllerForStatusBarStyle];
}

- (UIViewController *)childViewControllerForStatusBarHidden
{
    if ([self.presentedFSViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController *navigationController = (UINavigationController *)self.presentedFSViewController;
        return [navigationController.topViewController mz_childTargetViewControllerForStatusBarStyle];
    }
    return [self.presentedFSViewController mz_childTargetViewControllerForStatusBarStyle];
}

其他

/**
 Returns whether the form sheet controller should dismiss after background view tap.
 By default, this is NO
 */
@property (nonatomic, assign) BOOL shouldDismissOnBackgroundViewTap UI_APPEARANCE_SELECTOR;

/**
 The handler to call when user tap on background view
 */
@property (nonatomic, copy) MZFormSheetBackgroundViewTapCompletionHandler didTapOnBackgroundViewCompletionHandler;

MZFormSheetController+SVProgressHUD

  • 如果要让 SVProgressHUD 与 MZFormSheetController 一起使用,您只需从 MZFormSheetController+SVProgressHUD 目录中导入 #import "MZFormSheetController+SVProgressHUD.h" 即可。

已知问题

  • 在从 MZFormSheetController 等,无法设置模糊的 UINavigationBar。
    如果您不想在 iOS7 中有 UINavigationBar 内部的白色阴影,应该将 UINavigationBar 的 translucent 属性设置为 NO。

  • 如果您使用模糊背景,iPad 3 Retina 上会有巨大的延迟。
    我建议您关闭 iPad 3 Retina 的背景模糊。

  • 如果您想在上 MZFormSheetController 之上展示模态视图控制器,您必须从 formSheetController 展示,例如

// Easiest way:
[[[MZFormSheetController formSheetControllersStack] lastObject] presentViewController:navHistorico animated:YES completion:^{

}];

// Navigation Controller as a root of presentedFormSheetController:
[self.navigationController.formSheetController presentViewController:vc animated:YES completion:^{

}];

// View Controller as a root of presentedFormSheetController:
[self.formSheetController presentViewController:vc animated:YES completion:^{

}];

自动布局

MZFormSheetController 支持 autolayout。

需求

MZFormSheetController 需要iOS 5.x 或更高版本。

框架:'QuartzCore', 'Accelerate'

特别感谢

如果您觉得这个文档有用,我会很乐意看到您的感谢tweet。

特别感谢Kevin Cao,他编写了一些在MZFormSheetController中显示表单时使用的过渡代码和新键窗口的概念。

我还要感谢Daryl Ginn,他的设置弹出菜单给了我很多灵感。

Storyboard

MZFormSheetController支持Storyboard。

MZFormSheetSegue是一个自定义Storyboardsegue,它使用默认的MZFormSheetController设置。

ARC

MZFormSheetController使用ARC。

联系

Michal Zaborowski

Twitter

Bitdeli Badge