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

Posted

技术标签:

【中文标题】UISplitViewController 从任何地方平移到主视图【英文标题】:UISplitViewController pan to primary view from anywhere 【发布时间】:2015-09-29 22:38:31 【问题描述】:

对不起,冗长的解释,但这个问题 - 或类似的问题 - 已被问过几次,我还没有找到满意的答案。我正在 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】:

所以我一直在制作一个平滑的平移手势子类。目前,它的功能类似于 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];

【讨论】:

我相信将主视图添加为当前视图后面的子视图的所有必要信息都在UIView class reference 好的,所以我能够弄清楚这一点。我最后问了另一个非常相似的问题,但没有这个问题那么开放。我能够在当前可见视图后面添加 masterview 的图像:***.com/questions/32954552/…

以上是关于UISplitViewController 从任何地方平移到主视图的主要内容,如果未能解决你的问题,请参考以下文章

从 UINavigationController 切换到 UISplitviewController

从 UITabBarController 推送的 UISplitViewController

从 UISplitViewController 呈现的 modalViewController 出现方向错误

UISplitViewController - 从详细信息更新主表视图

从 UISplitView 呈现全屏模式视图?

从 UISplitViewController 显示时,UITableViewController 自动滚动停止考虑键盘