如何将UIPageControl元素放在UIPageViewController中的滑动页面之上?

关于AppCoda关于如何使用UIPageViewController实现应用程序的教程,我想在页面顶部而不是底部使用自定义页面控件元素。

当我将一个页面控件元素放在将要显示的单个视图之上时,逻辑结果是控件元素与页面视图一起滚动离开屏幕。

如何将控制元素放置在视图的顶部以便页面视图是全屏幕的(就像图像一样),这样用户就可以看到固定控制元素下面的视图了?

我附上了一个示例截图 – 学分到AppCoda和path :

在这里输入图像说明

经过进一步调查和search, 我发现了一个解决scheme ,也在stackoverflow。

关键是要发送到自定义UIPageControl元素的以下消息:

 [self.view bringSubviewToFront:self.pageControl]; 

AppCoda教程是此解决scheme的基础 :

RootViewController顶部添加一个UIPageControl元素 – 带有箭头的视图控制器。

在您的ViewController.m创build一个相关的IBOutlet元素。

viewDidLoad方法中,你应该添加下面的代码作为添加所有子视图之后调用的最后一个方法。

 [self.view bringSubviewToFront:self.pageControl]; 

要根据当前内容视图的pageIndex分配当前页面,可以将以下内容添加到UIPageViewControllerDataSource方法中:

 - (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { // ... index--; [self.pageControl setCurrentPage:index]; return [self viewControllerAtIndex:index]; } - (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { // ... index++; [self.pageControl setCurrentPage:index]; // ... return [self viewControllerAtIndex:index]; } 

我没有代表评论这个答案,但我真的很喜欢它。 我改进了代码,并将其转换为swift,用于下面的UIPageViewController的子类:

 class UIPageViewControllerWithOverlayIndicator: UIPageViewController { override func viewDidLayoutSubviews() { for subView in self.view.subviews as! [UIView] { if subView is UIScrollView { subView.frame = self.view.bounds } else if subView is UIPageControl { self.view.bringSubviewToFront(subView) } } super.viewDidLayoutSubviews() } } 

干净,它运作良好。 不需要维护任何东西,只要让你的页面视图控制器成为这个类的一个实例,或者让你的自定义页面视图控制器类inheritance自这个类。

sn3ek你的回答让我感受到了大部分的方式。 虽然我没有使用viewControllerCreation方法设置当前页面。

我做我的ViewController also UIPageViewController的委托。 然后我在那个方法中设置PageControlCurrentPage 。 使用维护的pageIndex我是原始文章中提到的ContentViewController

 - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { APPChildViewController *currentViewController = pageViewController.viewControllers[0]; [self.pageControl setCurrentPage:currentViewController.pageIndex]; } 

不要忘记添加到viewDidLoad

 self.pageViewController.delegate = self; 

为了跟上PropellerHead的评论, ViewController的接口将具有这种forms

 @interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate> 

简单地通过inheritanceUIPageViewController并覆盖viewDidLayoutSubviews,可以达到同样的效果,如下所示:

 -(void)viewDidLayoutSubviews { UIView* v = self.view; NSArray* subviews = v.subviews; if( [subviews count] == 2 ) { UIScrollView* sv = nil; UIPageControl* pc = nil; for( UIView* t in subviews ) { if( [t isKindOfClass:[UIScrollView class]] ) { sv = (UIScrollView*)t; } else if( [t isKindOfClass:[UIPageControl class]] ) { pc = (UIPageControl*)t; } } if( sv != nil && pc != nil ) { // expand scroll view to fit entire view sv.frame = v.bounds; // put page control in front [v bringSubviewToFront:pc]; } } [super viewDidLayoutSubviews]; } 

那么就没有必要维护一个独立的UIPageControl等等。

你必须实现一个自定义的UIPageControl并将其添加到视图。 正如其他人所说的,必须调用view.bringSubviewToFront(pageControl)

我有一个视图控制器的例子 ,所有的代码在UIPageControl设置一个自定义的UIPageControl (在storyboard中)

有2种方法需要执行来设置当前页面指示符。

 func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) { pendingIndex = pages.indexOf(pendingViewControllers.first!) } func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { if completed { currentIndex = pendingIndex if let index = currentIndex { pageControl.currentPage = index } } } 

这是一个RxSwift / RxCocoa答案,我看了其他答复后放在一起。

 let pages = Variable<[UIViewController]>([]) let currentPageIndex = Variable<Int>(0) let pendingPageIndex = Variable<(Int, Bool)>(0, false) let db = DisposeBag() override func viewDidLoad() { super.viewDidLoad() pendingPageIndex .asDriver() .filter { $0.1 } .map { $0.0 } .drive(currentPageIndex) .addDisposableTo(db) currentPageIndex.asDriver() .drive(pageControl.rx.currentPage) .addDisposableTo(db) } func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { if let index = pages.value.index(of: pendingViewControllers.first!) { pendingPageIndex.value = (index, false) } } func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { pendingPageIndex.value = (pendingPageIndex.value.0, completed) } 

Swifty 2的答案非常基于@ zerotool的回答。 只需要子类UIPageViewController,然后添加这个覆盖find滚动视图,并调整它。 然后抓住页面控件并将其移动到其他任何地方的顶部。 您还需要设置页面控件背景色来清除。 最后两行可以在你的应用程序委托。

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() var sv:UIScrollView? var pc:UIPageControl? for v in self.view.subviews{ if v.isKindOfClass(UIScrollView) { sv = v as? UIScrollView }else if v.isKindOfClass(UIPageControl) { pc = v as? UIPageControl } } if let newSv = sv { newSv.frame = self.view.bounds } if let newPc = pc { self.view.bringSubviewToFront(newPc) } } let pageControlAppearance = UIPageControl.appearance() pageControlAppearance.backgroundColor = UIColor.clearColor() 

顺便说一句 – 我没有发现任何无限循环,如上所述。