这是我到达的API。它由三个组件组成 - 普通视图控制器想要创建转换到另一个视图控制器,自定义容器视图控制器和转换类。转换类如下所示:
@interface TZInteractiveTransition : NSObject
@property(strong) UIView *fromView;
@property(strong) UIView *toView;
@property(assign, nonatomic) CGFloat phase;
@property(assign, readonly, getter = isCommitted) BOOL committed;
- (void) prepareToRun;
- (void) cleanup;
@end
从这个抽象类中,我派生出了具体的推动、旋转等过渡效果。大部分工作都在容器控制器中完成(稍微简化了一下):
@interface TZTransitionController : UIViewController
@property(strong, readonly) TZInteractiveTransition *transition;
- (void) startPushingViewController: (TZViewController*) controller withTransition: (TZInteractiveTransition*) transition;
- (void) startPoppingViewControllerWithTransition: (TZInteractiveTransition*) transition;
- (void) endTransitionWithCompletion: (dispatch_block_t) completion;
@end
为了让事情更加清晰,这就是过渡开始的方式:
- (void) startPushingViewController: (TZViewController*) controller withTransition: (TZInteractiveTransition*) transition
{
NSParameterAssert(controller != nil);
NSParameterAssert([controller parentViewController] == nil);
[self setTransition:transition];
[_transition setFromView:[_currentViewController view]];
[_transition setToView:[controller view]];
[_transition prepareToRun];
[_transition setPhase:0];
}
TZViewController
只是一个简单的UIViewController
子类,它持有一个指向转场控制器的指针(非常类似于navigationController
属性)。我使用类似于UIPanGestureRecognizer
的自定义手势识别器来驱动过渡,以下是视图控制器中手势回调代码的结构:
- (void) handleForwardPanGesture: (TZPanGestureRecognizer*) gesture
{
TZTransitionController *transitionController = [self transitionController];
switch ([gesture state]) {
case UIGestureRecognizerStateBegan:
[transitionController
startPushingViewController:
withTransition:[TZCarouselTransition fromRight]];
break;
case UIGestureRecognizerStateChanged: {
CGPoint translation = [gesture translationInView:[self view]];
CGFloat phase = fabsf(translation.x)/CGRectGetWidth([[self view] bounds]);
[[transitionController transition] setPhase:phase];
break;
}
case UIGestureRecognizerStateEnded: {
[transitionController endTransitionWithCompletion:NULL];
break;
}
default:
break;
}
}
我对结果感到满意 - 它相当简单,不使用任何黑科技,易于通过新的转换进行扩展,并且视图控制器中的代码相对较短和简单。我唯一的抱怨是我必须使用自定义容器控制器,所以我不确定它如何与标准容器和模态控制器配合使用。