UIPageViewController检测向前或向后滑动时的方法

6

我希望能够使用 UIPageViewController 来跟踪索引。每当我滑动时,我需要执行 index++ 或者 index-- 操作。下面这个委托方法会在你向前或向后滑动时被调用:

- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    // If the page did not turn
    if (!completed)
    {
        // You do nothing because whatever page you thought
        // the book was on before the gesture started is still the correct page
        return;
    }

    // I want to check here whenever the page was swiped back or further
}

如何在该方法中检查用户是否向后或向前滑动?我知道有两个数据源方法“viewControllerAfterViewController”和“viewControllerBeforeViewController”,但我无法检查页面转换是否已完成(而我可以在上述方法中执行此操作),有什么想法,我如何知道用户在上述方法中向后滑动还是向前滑动?

4个回答

6

使用协议:

MyClass : UIViewController <UIPageViewControllerDataSource,UIPageViewControllerDelegate

声明属性:

@property(nonatomic) NSInteger currentIndex;
@property(nonatomic) NSInteger nextIndex;

在这些方法中:

-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
    NewsTableViewController *controller  = [pendingViewControllers firstObject];
    self.nextIndex = [self.arrViews indexOfObject:controller];
}

-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
    if (completed) {
        self.currentIndex = self.nextIndex;
    }
    self.nextIndex = 0;
}

在那里,您将获得当前页面。感谢Corey Floyd在此处的帮助。


nextIndex 应该等于 currentIndex + 1。在 didFinishAnimating 中,检查新的 currentIndex == nextIndex,如果是向左滑动,则为左滑,否则为右滑。 - huync

4
根据文档,似乎没有办法判断用户是向前还是向后滑动页面。布尔值“finished”将告诉您用户是否完成了页面翻转。
解决方法:
创建一个int变量,并使用viewControllerAfterViewController和viewControllerBeforeViewController方法增加或减少变量的值。使用该变量来测试他们是否向前或向后移动。
编辑:您可以使用文档中的presentationIndexForPageViewController。
编辑2:检查此链接,有一个名为setViewControllers:direction:animated:completion:的方法,其中方向将是UIPageViewControllerNavigationDirectionForward或UIPageViewControllerNavigationDirectionReverse。
编辑3:代码 - 假设您知道哪个视图控制器将被前进或后退调用:
在您的appDelegate上创建一个变量和一个setter方法。
int indexVar;

- (void)setIndex:(int)indexVar;

然后在您的视图控制器上(向前或向后),要么增加该值,要么减少该值(viewDidLoad):

(AppDelegate *)[[UIApplication sharedApplication] delegate] setIndex:<whatever>];

大致如此。这不是实现你目标的确切方法,但希望能让你朝着正确的方向前进。


问题在于我无法在这两个函数中跟踪索引...因为如果无法检查转换是否完成,则无需增加或减少索引(例如,如果您抓住页面但不翻到下一页)。 - nonuma
1
我已根据您的评论编辑了我的答案。如果用户向前或向后移动,presentationIndex 才会上下更改。 - Jordan
1
答案在我的回答的Edit 2引用的页面上。在那个实例方法中,有一个名为completion的参数,它是一个块,在页面翻转动画完成或未完成时调用。 - Jordan
1
我明白了。那么解决方案就是使用变量。让我更新我的答案,并附上代码。 - Jordan
这个索引变量放在UIPageViewController的实际视图控制器中会更有用,不是吗?请参考我的答案。然后你可以在视图控制器本身中处理所有这些事情——我认为它实际上应该在那里。:] - pxpgraphics
显示剩余3条评论

0

我认为最简单的解决方案是创建一个自己的ViewController类,并使用一个属性来跟踪当前显示的索引。在大多数情况下,我需要一个自定义的ViewController来管理我的PageViewController。在我的示例中,这是以下类。

@interface PageZoomViewController : UIViewController

@property (nonatomic) int pageIndex;

@end

然后在viewControllerAfter/Before方法中,您可以将索引传递给新页面。

-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {

    int nextPageIndex = ((PageZoomViewController *)viewController).pageIndex-1;

    PageZoomViewController *controller = [[PageZoomViewController alloc] initWithPageViewControlParent:self andFrame:[self frameForPagingScrollView] andPageIndex:nextPageIndex];

    return controller;
}

当下一页的动画完成后,您可以轻松地像这样设置当前索引。
-(void)pageViewController:(UIPageViewController *)thePageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {

    if(completed) {
        index = ((PageZoomViewController *)thePageViewController.viewControllers[0]).pageIndex;
    }
}

希望这能帮到你!


0

我是通过在每个ViewController类中创建协议来实现的,在viewWillAppear方法中调用协议方法。然后在PageViewController中,每当我实例化一个视图控制器时,我将其委托设置为PageViewController。 这是我的项目中的第三个ViewController(请注意,我在每个视图控制器中都这样做了)

@class ViewController3;
@protocol ViewControllerPageNumber <NSObject>

-(void)viewWillAppearMyPageNumber:(int)myPageNumber;

@end
@interface ViewController3 : UIViewController
@property (nonatomic, weak) id <ViewControllerPageNumber> delegate;
@end

并且在.m文件中的viewWillAppear方法中

-(void)viewWillAppear:(BOOL)animated{
    [self.delegate viewWillAppearMyPageNumber:3];//The 3 will be different for each ViewController 
}

接下来,在PageViewController.m中,每当我实例化一个视图控制器时,我都将其委托设置为self(或PageViewController)。viewCons只是一个字符串数组,其中包含我的视图控制器名称。
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
    id vc = [[NSClassFromString([viewCons objectAtIndex:index]) alloc] init];
    if([vc isMemberOfClass:[NSClassFromString(@"ViewController3") class]]){
        ViewController3 *vc3=(ViewController3 *) vc;
        vc3.delegate=self;
    }else if([vc isMemberOfClass:[NSClassFromString(@"ViewController2") class]]){
        ViewController2 *vc2=(ViewController2 *) vc;
        vc2.delegate=self;
    }else if([vc isMemberOfClass:[NSClassFromString(@"ViewController") class]]){
        ViewController *vc1=(ViewController *) vc;
        vc1.delegate=self;
    }
    return vc;
}

最后,我正在实现我的自定义委托方法,这在我的情况下是刷新我设置在PageViewController顶部的标签文本。
-(void)viewWillAppearMyPageNumber:(int)myPageNumber{
    [self refreshLabelsOnCurrentPageWithIndex:myPageNumber];
}

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