UISplitViewController从任何地方平移到主视图

时间:2015-09-29 22:38:32

标签: ios iphone uisplitviewcontroller uipangesturerecognizer

对于长篇大论的探索感到抱歉,但这个问题 - 或类似的东西 - 已被问过几次,我还没有找到一个满意的答案。我正在iOS 8中编写一个实现 UISplitViewController 的iPad应用程序。最近我一直试图让它在iPhone上运行。它很好地转移,一切都自动崩溃,后面的按钮包含在导航的左侧。杆

我的问题是我希望保持后退按钮功能从堆栈中弹出一个视图,但也能够平移回主视图,即使它上面有多个详细视图。理想情况下,我希望能够覆盖或重定向 interactivePopGestureRecognizer ,以便手势平滑地平移到主视图(在某些情况下,它可以在其上方堆叠1到4个详细视图) 。但是,我无法弄清楚如何做到这一点。

我当前的解决方案(下面的代码)是在详细视图控制器中禁用 interactivePopGestureRecognizer 并实现我自己的 ScreenEdgePanGestureRecognizer ,当触发时,执行 popToRootViewController 。我已经将 ScreenEdgePanGestureRecognizer 子类化,因此它将屏幕边缘平移视为离散的“滑动”(即,一旦检测到足够大的屏幕边缘滑动 - 将所有内容从堆栈中弹出以使主视图可见) 。

代码详细视图控制器停止interactivePopGestureRecognizer:

-(void)viewWillAppear : (BOOL) animated {

    [super viewWillAppear : animated];
    // stops navigation controller from responding to the default back swipe gesture
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled =NO;
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
}

// Disable the default back swipe gesture tied to automatically included back button
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

    if ([gestureRecognizer isEqual:self.navigationController.interactivePopGestureRecognizer]) {
        return NO;
    } else {
        return YES;        
    }

}

我认为没有必要为screenEdgePanGestureRecognizer包含我的子类,因为它与解决方案无关,我在这里询问的是一些伪代码,它显示了@selector在详细视图控制器中的作用:

- (IBAction)leftEdgeSwipe:(ScreenEdgeSwipeGestureRecognizer*)sender {
    if (sender.swipeIsValid) {
        [(UINavigationController *)self.splitViewController.viewControllers[0]
         popToRootViewControllerAnimated:YES];
    }
}

我尝试使用连续平移,但无法找到在背景中显示主视图的方法,因为我将当前视图拉到一边以提供干净,平滑的平移效果。我能够做到这一点,所以我可以移动当前视图,但背后只有一个灰色背景,我希望我的主要视图。

总结:如果确实无法将interactivePopGestureRecognizer更改为始终跳转到我的主视图(理想解决方案),那么任何有关如何将我自己的平滑平移回到我的主要信息的信息观点将不胜感激。

1 个答案:

答案 0 :(得分:0)

所以我一直在努力制作一个平滑的平移手势子类。目前它的功能类似于Apple的后退手势,除了它一直跳回到根视图控制器而不是从堆栈中弹出一个视图。唯一的问题是它在平移时还没有在后台显示主视图。一旦我解决了问题,我会更新答案。

这是子类:

#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>
#import "ScreenEdgeSwipeGestureRecognizer.h"



@interface ScreenEdgeSwipeGestureRecognizer ()

@property (nonatomic) UINavigationController* navController;

@end


@implementation ScreenEdgeSwipeGestureRecognizer{
    CGPoint _screenCenter;
    CGPoint _cumulativePanDistance;
}



- (id)initWithNavigationController:(UINavigationController*)navController {
    self = [super initWithTarget:self action:@selector(leftEdgePan:)];
    _screenCenter = CGPointZero;
    _cumulativePanDistance = CGPointZero;
    self.edges = UIRectEdgeLeft;
    self.navController = navController;
    return self;
}



- (IBAction)leftEdgePan:(ScreenEdgeSwipeGestureRecognizer*)sender {
    assert(sender == self);

    switch (self.state) {
        case UIGestureRecognizerStateBegan:
            [self initializePositions];
            break;

        case UIGestureRecognizerStateChanged:
            [self updatePositions];
            break;

        case UIGestureRecognizerStateEnded:
            [self animateViewBasedOnCurrentLocation];
            break;

        case UIGestureRecognizerStateCancelled:
            [self animateViewToCenter];
            break;

        default:
            break;
    }

    // Reset velocity of the pan so current velocity does not compound with velocity of next cycle
    [sender setTranslation:CGPointMake(0, 0) inView:sender.view];
}



- (void)initializePositions {
    _screenCenter = self.view.center;
    _cumulativePanDistance = CGPointZero;
}



- (void)updatePositions {
    // Track position of user touch event
    CGPoint deltaSinceLastCycle = [self translationInView:self.view];

    // View center = view center at last cycle + distance moved by user touch since last cycle
    self.view.center=CGPointMake((self.view.center.x +   deltaSinceLastCycle.x), self.view.center.y+ 0);

    // Update the total positive distance traveled by the user touch event.
    _cumulativePanDistance.x = _cumulativePanDistance.x + deltaSinceLastCycle.x;
}



- (void)animateViewBasedOnCurrentLocation {
    if (_cumulativePanDistance.x >= (_screenCenter.x - 50)){
        [self reset];
        [_navController popToRootViewControllerAnimated:YES];
    }else{
        [self animateViewToCenter];
        [self reset];
    }
}



- (void)animateViewToCenter {
    [UIView animateWithDuration:0.25 animations:^{self.view.center = self->_screenCenter;}];
}



- (void)reset {
    [super reset];
    _cumulativePanDistance = CGPointZero;
    self.state = UIGestureRecognizerStatePossible;
}

@end

以下是我在视图控制器中实例化识别器的方法:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    // Initialize the screen edge pan gesture recognizer.
    _masterNavigationController = self.splitViewController.viewControllers[0];

    ScreenEdgePanGestureRecognizer* edgePanRecognizer =  [[ScreenEdgeSwipeGestureRecognizer alloc] initWithNavigationController:_masterNavigationController];

    // Add recognizer to view this controller is bound to.
    [self.view addGestureRecognizer:_edgePanRecognizer];
}