UISplitViewController 从任何地方平移到主视图 [英] UISplitViewController pan to primary view from anywhere

查看:26
本文介绍了UISplitViewController 从任何地方平移到主视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,冗长的解释,但这个问题 - 或类似的问题 - 已经被问过几次,我还没有找到满意的答案.我正在 iOS 8 中编写一个实现 UISplitViewController 的 iPad 应用程序.最近我一直在尝试让它在 iPhone 上运行.它转移得很好,一切都会自动折叠,我的导航左侧包含一个后退按钮.吧.

Sorry for the long-winded explination, but this question - or something similar - has been asked a few times and I havent found a satisfactory answer. I am writing an iPad app in iOS 8 that implements UISplitViewController. Recently I have been attempting to get it to work on the iPhone. It transferred over pretty well, everything collapses automatically and a back button is included in the left side of my nav. bar.

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

My problem is that I want to keep the back button functionality to pop one view off the stack, but also be able to pan back to the primary view even if there are several detail views on top of it. Ideally, I want to be able to overwrite or redirect the interactivePopGestureRecognizer so that the gesture smoothly pans to the primary view (in some cases it can have anywhere from 1 to 4 detail views stacked on top of it). But, I cannot figure out how to do this.

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

My current solution (code below) is to disable the interactivePopGestureRecognizer in the detail viewcontroller and implement my own ScreenEdgePanGestureRecognizer that, when triggered, executes popToRootViewController. I've subclassed the ScreenEdgePanGestureRecognizer so it treats the screen edge pan as a discrete "swipe" (i.e. once a large enough screen edge swipe is detected - pop everything off the stack so the primary view is visible).

详细视图控制器代码以停止交互PopGestureRecognizer:

Code in detail view controller to stop 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 在细节视图控制器中的作用:

I didn't think it was necessary to include my subclass for the screenEdgePanGestureRecognizer because it has nothing to do with the solution I am asking about here is some pseudocode that shows what my @selector does in the detail viewcontroller:

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

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

I tried to use the continuous pan, but cannot find a way to present the primary view in the background as I am pulling the current view aside to give that clean, smooth panning effect. I am able to make it so I can move the current view around, but there is just a grey background behind it where I would want my primary view to be.

总结:如果确实没有办法改变interactivePopGestureRecognizer以始终跳转到我的主要视图(理想的解决方案),那么关于如何让我自己的平滑平移回到我的主要视图的任何信息将不胜感激.

Summation: If there is indeed no way to change the interactivePopGestureRecognizer to always jump to my primary view (ideal solution), then any info on how I can make my own smooth pan back to my primary view would be much appreciated.

推荐答案

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

So I have been messing around with making a smooth panning gesture subclass. Currently it functions similarly to Apple's back gesture except it jumps all the way back to the root view controller instead of popping one view off the stack. The only problem is that it does not yet show the primary view in the background while panning. I will update the answer once I get that worked out.

这是子类:

#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

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

Here is how I instantiate the recognizer in my view controller:

- (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];
}

这篇关于UISplitViewController 从任何地方平移到主视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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