视图控制器之间的交互式转换? [英] Interactive transitions between view controllers?

查看:122
本文介绍了视图控制器之间的交互式转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 UIView 动画API和视图控制器包含,当前的Cocoa Touch栈非常适合视图控制器之间的自动转换。

With the UIView animation API and view controller containment the current Cocoa Touch stack is very well suited for automatic transitions between view controllers.

我发现很难写的是视图控制器之间的交互式过渡。例如,当我只想使用推送动画替换另一个视图时,可以使用 UINavigationController 或使用containment API并自己编写转换。但是很常见的是,我想要转换为交互式,触摸控制:用户开始拖动当前视图,传入视图从侧面显示,过渡由平移触摸手势控制。用户可以只是平移一点窥视传入视图,然后平移回来,保持当前视图可见。如果手势结束低于某个阈值,则转换将被取消,否则会完成。

What I find hard to write are interactive transitions between view controllers. As an example, when I just want to replace one view with another using a push animation, I can use UINavigationController or use the containment API and write the transition myself. But it’s quite common that I want the transition to be interactive, touch-controlled: user starts dragging the current view, the incoming view appears from the side and the transition is controlled by the panning touch gesture. The user can just pan a little to "peek" at the incoming view and then pan back, keeping the current view visible. If the gesture ends below a certain treshold, the transition is cancelled, otherwise it’s completed.

(如果这还不够清楚,在iBooks中翻页,但在不同的视图控制器之间,并且推广到任何这样的交互式转换。)

(In case this is not clear enough, I’m talking about something like the page turn in iBooks, but between different view controllers, and generalized to any such interactive transition.)

我知道如何写这样的转换,知道太多关于转换 - 它占用了太多的代码。这甚至没有提到可以容易地有两个不同的交互式转换可能,在这种情况下,所讨论的控制器是充满了过渡代码,紧密耦合。

I know how to write such a transition, but the current view controller has to know too much about the transition – it takes up too much of its code. And that’s not even mentioning that there can easily be two different interactive transitions possible, in which case the controllers in question are full of the transition code, tightly coupled to it.

有没有抽象的模式,泛化交互式转换代码,并将其移动到一个单独的类或代码块?也许是一个库,甚至?

Is there a pattern to abstract, generalize the interactive transition code and move it into a separate class or code lump? Maybe a library, even?

推荐答案

这是我到达的API。它有三个组件 - 常规视图控制器,想要创建一个过渡到另一个,自定义容器视图控制器和过渡类。过渡类如下:

This is the API I have arrived at. There are three components to it – the regular view controller that wants to create a transition to another one, a custom container view controller, and a transition class. The transition class looks like this:

@interface TZInteractiveTransition : NSObject

@property(strong) UIView *fromView;
@property(strong) UIView *toView;

// Usually 0–1 where 0 = just fromView visible and 1 = just toView visible
@property(assign, nonatomic) CGFloat phase;
// YES when the transition is taken far enough to perform the controller switch
@property(assign, readonly, getter = isCommitted) BOOL committed;

- (void) prepareToRun;
- (void) cleanup;

@end



从这个抽象类派生具体的推送过渡,旋转等。大多数工作是在容器控制器(简化了一点):

From this abstract class I derive the concrete transitions for pushing, rotating etc. Most work is done in the container controller (simplified a bit):

@interface TZTransitionController : UIViewController

@property(strong, readonly) TZInteractiveTransition *transition;

- (void) startPushingViewController: (TZViewController*) controller withTransition: (TZInteractiveTransition*) transition;
- (void) startPoppingViewControllerWithTransition: (TZInteractiveTransition*) transition;

// This method finishes the transition either to phase = 1 (if committed),
// or to 0 (if cancelled). I use my own helper animation class to step
// through the phase values with a nice easing curve.
- (void) endTransitionWithCompletion: (dispatch_block_t) completion;

@end

为了使事情更清楚,过渡开始:

To make things a bit more clear, this is how the transition starts:

- (void) startPushingViewController: (TZViewController*) controller withTransition: (TZInteractiveTransition*) transition
{
    NSParameterAssert(controller != nil);
    NSParameterAssert([controller parentViewController] == nil);

    // 1. Add the new controller as a child using the containment API.
    // 2. Add the new controller’s view to [self view].
    // 3. Setup the transition:    
    [self setTransition:transition];
    [_transition setFromView:[_currentViewController view]];
    [_transition setToView:[controller view]];
    [_transition prepareToRun];
    [_transition setPhase:0];
}

TZViewController 只是一个简单的 UIViewController 子类,它包含一个指向转换控制器的指针(非常像 navigationController 属性)。我使用类似于 UIPanGestureRecognizer 的自定义手势识别器来驱动转换,这是视图控制器中手势回调代码的样子:

The TZViewController is just a simple UIViewController subclass that holds a pointer to the transition controller (very much like the navigationController property). I use a custom gesture recognizer similar to UIPanGestureRecognizer to drive the transition, this is how gesture callback code in the view controller looks:

- (void) handleForwardPanGesture: (TZPanGestureRecognizer*) gesture
{
    TZTransitionController *transitionController = [self transitionController];
    switch ([gesture state]) {
        case UIGestureRecognizerStateBegan:
            [transitionController
                startPushingViewController:/* build next view controller */
                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;
    }
}



我对结果感到满意 - ,没有使用hack,它很容易扩展与新的过渡和代码在视图控制器是相当短,简单。我唯一的抱怨是,我必须使用自定义容器控制器,所以我不知道如何与标准的容器和模态控制器。

I’m happy with the result – it’s fairly straightforward, uses no hacks, it’s easy to extend with new transitions and the code in the view controllers is reasonably short & simple. My only gripe is that I have to use a custom container controller, so I’m not sure how that plays with the standard containers and modal controllers.

这篇关于视图控制器之间的交互式转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆