学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

【译】Creating Custom Presentations

UIKit将你的视图控制器的content从content is presented 并在屏幕上显示的方式中分离出来。Presented视图控制器由底层presentation控制器对象管理,该对象管理用于显示视图控制器的视图的视觉样式。presentation控制器可以做以下事情:

  • 设置presented视图控制器的大小。
  • 添加自定义视图以更改显示内容的( the presented content)视觉外观。
  • 为任何自定义视图提供过渡动画。
  • 当应用程序的环境发生变化时,调整演示的视觉外观。

UIKit为标准的表示样式提供了presentation控制器。当你设置一个视图控制器的表示样式为UIModalPresentationCustom并提供一个适当的转换委托时,UIKit会使用你的自定义表示控制器。

The Custom Presentation Process

当你present一个presentation风格为UIModalPresentationCustom的视图控制器时,UIKit会寻找一个自定义的presentation控制器来管理presentation过程。随着presentation的进行,UIKit调用presentation控制器的方法,让它有机会设置任何自定义视图并将它们动画到相应的位置。

presentation控制器与任何动画对象(animator objects)一起工作来实现整体转换。animator对象将视图控制器的内容(contents)动画到屏幕上,而presentation控制器处理其他一切。通常,你的presentation控制器动画它自己的视图,但你也可以重写presentation控制器的presenttedview方法,让animator对象动画所有或部分视图。

在presentation过程中,UIKit:

  1. 调用转换委托的presentationcontrollerforpresenttedviewcontroller:presentingViewController:sourceViewController:方法来检索(retrieve)您的自定义presentation控制器

  2. 向过渡委托请求动画器和交互动画器对象(如果有的话)

  3. 调用表示控制器的presentationTransitionWillBegin方法

    这个方法的实现应该将任何自定义视图添加到视图层次结构中,并为这些视图配置动画。

  4. 从presentation控制器获取presenttedview

    此方法返回的视图由动画器对象动画到相应位置。通常,这个方法返回presented视图控制器的根视图。您的presentation控制器可以根据需要用自定义背景视图替换该视图。如果你指定了一个不同的视图,你必须将presented视图控制器的根视图嵌入到你的视图层次结构中。

  5. 执行过渡动画

    过渡动画包括由animator对象创建的主要动画,以及您配置为与主要动画一起运行的任何动画。有关过渡动画的信息,请参见过渡动画序列。
    在动画过程中,UIKit调用你的表示控制器的containerViewWillLayoutSubviews和containerViewDidLayoutSubviews方法,这样你就可以根据需要调整你的自定义视图的布局。

  6. 在转换动画完成时调用presentationTransitionDidEnd:方法

在dismissal期间,UIKit:

  1. 从当前可见的视图控制器获取自定义presentation控制器

  2. 向过渡委托请求动画器和交互动画器对象(如果有的话)

  3. 调用表示控制器的dissaltransitionwillbegin方法

    这个方法的实现应该将任何自定义视图添加到视图层次结构中,并为这些视图配置动画。

  4. 从表示控制器获取已经 presentedView

  5. 执行过渡动画

    过渡动画包括由animator对象创建的主要动画,以及您配置为与主要动画一起运行的任何动画。有关过渡动画的信息,请参见过渡动画序列。
    在动画过程中,UIKit调用你的表示控制器的containerViewWillLayoutSubviews和containerViewDidLayoutSubviews方法,这样你就可以删除任何自定义约束。

  6. 当过渡动画结束时调用dissaltransitiondidend:方法

在presentation过程中,你的表示控制器的frameofpresenttedviewincontainerviewpresenttedview方法可能会被调用几次,所以你的实现应该很快返回。同样,你的presenttedview方法的实现不应该尝试设置视图层次结构。在调用方法时,视图层次结构应该已经配置好了。

Creating a Custom Presentation Controller

要实现自定义的presentation风格,子类UIPresentationController并添加代码来创建presentation的视图和动画。在创建自定义presentation控制器时,考虑以下问题:

  • 您想添加哪些视图?

  • 你想如何在屏幕上动画任何其他视图?

  • 呈现的视图控制器应该是多大?

  • 在水平规则类和水平紧凑类之间,表示应该如何适应?

  • 当呈现结束时,呈现视图控制器的视图应该被移除吗?

所有这些决策都需要重写UIPresentationController类的不同方法。

Setting the Frame of the Presented View Controller

您可以修改当前视图控制器(presented view controlle)的框架矩形(frame rectangle ),使其只填充可用空间的一部分。默认情况下,presented view controller的大小完全填满容器视图的frame。要改变frame rectangle,重写presentation控制器的frameofpresenttedviewincontainerview方法。清单11-1显示了一个例子,其中frame被更改为只覆盖容器视图的右半部分。在这种情况下,presentation控制器使用背景变暗(dimming)视图来覆盖容器的另一半。

1
2
3
4
5
6
7
8
9
10
11
//  Listing 11-1 Changing the frame of a presented view controller
- (CGRect)frameOfPresentedViewInContainerView {
CGRect presentedViewFrame = CGRectZero;
CGRect containerBounds = [[self containerView] bounds];

presentedViewFrame.size = CGSizeMake(floorf(containerBounds.size.width / 2.0),
containerBounds.size.height);
presentedViewFrame.origin.x = containerBounds.size.width -
presentedViewFrame.size.width;
return presentedViewFrame;
}

Managing and Animating Custom Views

自定义presentations通常包括向presented的内容添加自定义视图。使用自定义视图来实现纯视觉装饰(adornments),或者使用它们来向表示添加实际(practical)行为。例如,背景视图可能包含手势识别器来跟踪presented内容范围之外的特定操作。

presentation控制器负责创建和管理与其presentation相关联的所有自定义视图。通常,在初始化表示控制器期间创建自定义视图。清单11-2显示了创建自己的变暗视图的自定义视图控制器的初始化方法。该方法创建视图并执行一些最小配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
// Listing 11-2 Initializing the presentation controller
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
presentingViewController:(UIViewController *)presentingViewController {
self = [super initWithPresentedViewController:presentedViewController
presentingViewController:presentingViewController];
if(self) {
// Create the dimming view and set its initial appearance.
self.dimmingView = [[UIView alloc] init];
[self.dimmingView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.4]];
[self.dimmingView setAlpha:0.0];
}
return self;
}

使用presentationTransitionWillBegin方法将自定义视图动画到屏幕上。在这种方法中,配置您的自定义视图并将它们添加到容器视图,如清单11-3所示。使用presented视图控制器或presenting视图控制器的转换协调器来创建任何动画。不要在此方法中修改presented视图控制器的视图。动画器对象负责将presented视图控制器动画到你从frameofpresenttedviewincontainerview方法返回的frame rectangle中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Listing 11-3 Animating the dimming view onto the screen
- (void)presentationTransitionWillBegin {
// Get critical information about the presentation.
UIView* containerView = [self containerView];
UIViewController* presentedViewController = [self presentedViewController];

// Set the dimming view to the size of the container's
// bounds, and make it transparent initially.
[[self dimmingView] setFrame:[containerView bounds]];
[[self dimmingView] setAlpha:0.0];

// Insert the dimming view below everything else.
[containerView insertSubview:[self dimmingView] atIndex:0];

// Set up the animations for fading in the dimming view.
if([presentedViewController transitionCoordinator]) {
[[presentedViewController transitionCoordinator]
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>
context) {
// Fade in the dimming view.
[[self dimmingView] setAlpha:1.0];
} completion:nil];
}
else {
[[self dimmingView] setAlpha:1.0];
}
}

在presentation结束时,使用presentationTransitionDidEnd:方法来处理由于取消presentation而引起的任何清理。交互式动画对象如果没有满足阈值(threshold)条件,可能会取消转换。当这种情况发生时,UIKit调用presentationTransitionDidEnd:方法,值为NO。当取消发生时,删除您在presentation开始时添加的任何自定义视图,并将任何其他视图返回到它们之前的配置,如清单11-4所示。

1
2
3
4
5
6
//Listing 11-4 Handling a cancelled presentation
- (void)presentationTransitionDidEnd:(BOOL)completed {
// If the presentation was canceled, remove the dimming view.
if (!completed)
[self.dimmingView removeFromSuperview];
}

当视图控制器dismissed时,使用dismissalTransitionDidEnd:方法从视图层次结构中移除你的自定义视图。如果你想动画视图的消失,在dismissalTransitionDidEnd:方法中设置这些动画。清单11-5显示了在前面的示例中删除暗光视图( dimming view)的两种方法的实现。总是检查disdissaltransitiondidend:方法的参数,看看dismissal是成功的还是被取消了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Listing 11-5 Dismissing the presentation’s views
- (void)dismissalTransitionWillBegin {
// Fade the dimming view back out.
if([[self presentedViewController] transitionCoordinator]) {
[[[self presentedViewController] transitionCoordinator]
animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>
context) {
[[self dimmingView] setAlpha:0.0];
} completion:nil];
}
else {
[[self dimmingView] setAlpha:0.0];
}
}

- (void)dismissalTransitionDidEnd:(BOOL)completed {
// If the dismissal was successful, remove the dimming view.
if (completed)
[self.dimmingView removeFromSuperview];
}

Vending Your Presentation Controller to UIKit

当presenting一个视图控制器时,执行以下操作来使用你的自定义presentation控制器显示它:

  • 设置presented视图控制器的modalPresentationStyle属性为UIModalPresentationCustom

  • 给presented视图控制器的transitioningDelegate属性分配一个转换委托。

  • 实现转换委托的presentationcontrollerforpresenttedviewcontroller:presentingViewController:sourceViewController:方法。

UIKit调用你的转换委托的presentationcontrollerforpresenttedviewcontroller:presentingViewController:sourceViewController:方法当它需要你的表示控制器时。这个方法的实现应该像清单11-6中那样简单。只需创建您的表示控制器,配置它并返回它。如果你从这个方法中返回nil, UIKit会使用全屏显示样式来显示视图控制器。

1
2
3
4
5
6
7
8
9
10
11
//Listing 11-6 Creating a custom presentation controller
- (UIPresentationController *)presentationControllerForPresentedViewController:
(UIViewController *)presented
presentingViewController:(UIViewController *)presenting
sourceViewController:(UIViewController *)source {

MyPresentationController* myPresentation = [[MyPresentationController]
initWithPresentedViewController:presented presentingViewController:presenting];

return myPresentation;
}

参考

Creating Custom Presentations