处理一个带滑动的视图控制器,可以通过任何方向滑动显示

6
我正在开发一个适用于iOS6+的应用程序。在应用程序的某个点上,它将具有一个主视图控制器。
我希望这个主要的视图控制器能够处理屏幕左右滑动,然后显示另一个视图控制器。
在核心iOS6+中是否有一种简单的方法来完成这个功能,或者我应该寻找其他库等?
我已经在应用程序的其他地方使用了侧滑菜单样式。我也理解并可以找到无数的替代品。
我正在寻找的是有一个视图控制器(充当“中间”),当他们向左/右滑动时会显示另一个视图控制器。他们然后可以向相反的方向滑动回去,或者点击一个返回按钮返回到主控制器。
编辑-
具体而言,我正在寻找以下功能: 预加载将要滑入的控制器。 当滑动发生时(正在发生)…控制器会随着触摸拖动/滑动。 同样的拖动/滑动方式在控制器被向左/右滑动的情况下发生。
编辑2 -
我正在寻找使用手指拖动视图控制器的功能。根据拖动的方向不同,它将拉入相同的视图控制器。
也就是说,布局将是: [用于拖动的VC] [主控制器] [用于拖动的VC]。 如果用户从左向右或从右向左滑动,则另一个控制器会在其上方拖动,他们可以使用相反的入口滑动返回到主控制器。
5个回答

6

我最喜欢的侧边抽屉控制器是:https://github.com/mutualmobile/MMDrawerController

MMDrawerController非常灵活,可以完成您提到的所有功能:

  • 支持左右两个控制器
  • 预加载侧边控制器
  • 使用手势“拖动”打开

如果您正在使用Storyboard,则可以使用此扩展程序来获得Storyboard支持:https://github.com/TomSwift/MMDrawerController-Storyboard

编辑:

另一个选项可能是使用UIPageViewController并将转换样式设置为UIPageViewControllerTransitionStyleScrollhttps://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html

这将具有“拉入”侧边视图控制器的行为,而不是“揭示”它们。

编辑2:根据要求提供示例

您唯一真正复杂的要求是相同的视图控制器用于左右两侧。这意味着我们必须跟踪视图控制器被呈现的位置,以便我们可以正确地管理我们的数据源。如果没有这个要求,我们可以使用数组来支持我们的数据源,并从中派生下一个/上一个。

首先是Storyboard。Storyboard有三个视图控制器:1)UIPageViewController,我将其子类化为TSPageViewController。不要忘记将页面控制器的转换样式属性设置为“滚动”。2)“中心”视图控制器,和3)“侧边”视图控制器。对于中心和侧边,我将每个的Storyboard ID分别设置为“center”和“side”。对于此示例,中心和侧面控制器都是普通的UIViewControllers,我设置了它们的backgroundColor以区分它们。

enter image description here

其次,页面视图控制器:

.h

@interface TSPageViewController : UIPageViewController
@end

.m

@interface TSPageViewController () <UIPageViewControllerDataSource>
@end

@implementation TSPageViewController
{
    UIViewController* _side;

    UIViewController* _center;
}

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.dataSource = self;

    _side = [self.storyboard instantiateViewControllerWithIdentifier: @"side"];
    _center = [self.storyboard instantiateViewControllerWithIdentifier: @"center"];

    [self setViewControllers: @[_center]
                   direction: UIPageViewControllerNavigationDirectionForward
                    animated: NO
                  completion: nil];
}

- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    if ( viewController == _center )
    {
        _side.title = @"right";
        return _side;
    }

    if ( viewController == _side && [_side.title isEqualToString: @"left"] )
    {
        return _center;
    }

    return nil;
}

- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    if ( viewController == _center )
    {
        _side.title = @"left";
        return _side;
    }

    if ( viewController == _side && [_side.title isEqualToString: @"right"] )
    {
        return _center;
    }

    return nil;
}

@end

需要特别注意的是,这里唯一特殊的地方在于跟踪侧边控制器当前是“左”还是“右”。但此实现存在一个问题,即它依赖于UIPageViewController的行为来避免“提前分页”和缓存视图控制器(如果这样做,我们的逻辑将会混乱)。因此,您可能需要考虑更强大的机制来跟踪视图控制器当前所在的位置。为此,您可能需要引入自己的滑动手势识别器并使用其中的数据来驱动左/右跟踪。

如果您可以放弃使用相同的视图控制器作为左、右两侧,则可以拥有单独的左、右、中心控制器,存储在数组中,并根据数组中的内容返回下一个/上一个控制器。这样更容易且更健壮!


我认为这对手头的任务有点过度设计。我已经查看了一堆滑动视图控制器,并在应用程序中使用其中一个作为菜单系统。我只是想要加载一个主控制器,然后有一个“底部”的第二个控制器,当用户向左或右拖动/滑动时显示它。 然后当他们向相反方向滑动时,主控制器再次显示。这不是我可以简单实现而不是每个这些滑动式菜单风格gits提供的不同路线之一吗? - StuartM
对我来说,这似乎并不过度。您所描述的正是这些控制器的设计目的。您可以自己开发,但为什么呢? - TomSwift
Tom,我想实现这种方法,但是我在思考如何实现时遇到了困难,你有其他信息吗?我正在使用storyboards,并且将设置两个控制器。一个用于主要内容,另一个控制器可以从任一侧拉入。我不确定如何设置,因为苹果的示例使用了DataSource等,而这是一种简单的UIViewController方法。是否有其他信息或有关此设置的有用链接? - StuartM
@StuartM - 我已经为你添加了一个示例。祝你好运! - TomSwift
太好了,谢谢Tom。这正是我想要的结果。这太好了,而且我不需要使用任何第三方工具来完成这个任务——这更加完美! - StuartM

1

这些是针对iOS7+的,我正在针对iOS6。 - StuartM
啊,抱歉,我错过了那个。已经在上面编辑过答案了。 - ader

0

您可以通过一些Cocoa控件来实现,例如:

https://github.com/Inferis/ViewDeck

https://github.com/gotosleep/JASidePanels

编辑:提案二,使用带有scrollView的控制器:

// Allocate all the controlelrs you need
MyFirstViewController *first = [[MyFirstViewController alloc] init];
MySecondViewController *second= [[MySecondViewController alloc] init];
MyThirdViewController *third = [[MyThirdViewController alloc] init];

// Adjust the frames of the controllers
first.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
second.view.frame = CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);
third .view.frame = CGRectMake(0, 2 * self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);

// Add controllers as subViews to the scrollView
[self.scrollView addSubview:self.first.view];
[self.scrollView addSubview:self.second.view];
[self.scrollView addSubview:self.third.view];

// Set the scrollView contentSize and paging
self.scrollView.contentSize = CGRectMake(self.view.frame.size.width * 3, self.view.frame.size.height);
self.scrollView.pagingEnabled = YES;

// Scroll to the middle view initally
[self.scrollView scrollRectToVisible:CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height) animated:NO];

上面的代码是凭记忆编写的,我可能给一些东西命名不正确,而且处理子视图的方法不止一种。在注释中提到的pageViewController也可以使用。

这些只是滑动菜单控制器。实际上,我已经在我的应用程序中使用了一个。我特别想要能够从两侧拖动/滑动的效果,因此想法是手动创建还是有一个具体的示例可以实现这个功能。我已经尝试了大约50个这样的控制器。 - StuartM
为什么不直接使用带分页的简单scrollView呢? - Adis
我不明白为什么这样做不行?你有没有关于如何设置它们的示例,我能否设置分页但不显示图标来指示此操作。我只需要在中间加载一个主控制器,并能够从左侧或右侧拖动“下层”视图控制器,并从最初拖动的相反方向返回到中间。 - StuartM
只需创建一个带有scrollView的viewController(它甚至可以是您的中心控制器或任何其他控制器),将其他控制器的视图作为子视图添加,并以编程方式滚动到中间位置。我会在答案中更新一些示例代码。 - Adis
与其自己编写UIScrollView解决方案,不如直接使用UIPageViewController。https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html - TomSwift
@TomSwift - 你能提供一个使用页面控制器实现这个的例子吗?苹果提供的方法不容易理解或转换成这种方法。 - StuartM

0

-1

我猜问题是关于Storyboard中视图控制器的布局。它们将如何排列。如果我想用滑动来加载相同的控制器。理想情况下,我希望能够滑动并“拖动”新的视图控制器,手指仍然按下,以便它可以被拖入。对于滑动也是一样的。 - StuartM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接