2015-09-28 54 views
13

我有一個簡單的UIPageViewController,它在頁面底部顯示默認的UIPageControl。我想知道是否有可能修改UIPageControl的位置,例如在屏幕的頂部而不是底部。 我一直在環顧四周,只發現舊的討論,說我需要創建我自己的UIPageControl。 用iOS8和9更簡單嗎? 謝謝。如何在iOS> = 8.0中更改UIPageControl的位置?

回答

31

是的,你可以添加自定義頁面控制器。

self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50, self.view.frame.size.width, 50)]; // your position 

[self.view addSubview: self.pageControl]; 

然後取出

(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController 

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController 

然後添加其他委託方法:

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers 
{ 
    PageContentViewController *pageContentView = (PageContentViewController*) pendingViewControllers[0]; 
    self.pageControl.currentPage = pageContentView.pageIndex; 
} 
+0

感謝您的回答。如果我理解的很好,刪除presentationCountForPageViewController:和presentationIndexForPageViewController:的部分是隱藏默認頁面控制器,是不是? –

+0

如果它的幫助完整,請接受它。 – Jan

+0

是的,所以你可以自定義頁面控制 – Jan

7

的Shameerjan答案是非常好的,但它需要一件事正確地工作,那爲實現另一種委託方法:

func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { 

    // If user bailed our early from the gesture, 
    // we have to revert page control to previous position 
    if !completed { 
     let pageContentView = previousViewControllers[0] as! PageContentViewController; 
     self.pageControl.currentPage = pageContentView.pageIndex; 
    } 
} 

這是因爲,如果不這樣做,如果你移動頁面控件只是非常輕微,它會回到原來的位置 - 但是,頁面控制會顯示不同的頁面。

希望它有幫助!

+0

這是一個很好的評論,但你有Swift和Objective-C代碼的混合。也許..讓pageContentView = previousViewControllers.first –

+0

真,我固定它,謝謝 –

2

爲SWIFT:

self.pageController = UIPageControl(
            frame: CGRect(
             x: 0, 
             y: self.view.frame.size.height - 50, 
             width: self.view.frame.size.width, 
             height: 50 
            ) 
            ) 

self.view.addSubview(pageController) 

記得使用pageController.numberOfPages和委託瀏覽量

然後取出

func presentationCountForPageViewController(
    pageViewController: UIPageViewController 
) -> Int 

func presentationIndexForPageViewController(
    pageViewController: UIPageViewController 
) -> Int 

然後添加其他DELE門方法:

func pageViewController(
    pageViewController: UIPageViewController, 
    willTransitionToViewControllers pendingViewControllers:[UIViewController]){ 
     if let itemController = pendingViewControllers[0] as? PageContentViewController { 
      self.pageController.currentPage = itemController.pageIndex 
     } 
    } 
} 
+0

什麼是網頁索引? :/ –

+0

值類型「PageViewController」沒有成員「的PageController」 –

3

是的,Shameerjan答案是非常好的,但不是增加另一個頁面的控制,你可以使用默認的頁面指示:

- (UIPageControl*)pageControl { 
for (UIView* view in self.view.subviews) { 
    if ([view isKindOfClass:[UIPageControl class]]) { 
     //set new pageControl position 
     view.frame = CGRectMake(100, 200, width, height); 
     return (id)view; 
    } 
} 
return nil; 
} 

然後再擴展UIPageViewController規模覆蓋向上的底部間隙:所述pageviewcontroller的

//somewhere in your code 
self.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height+40); 
7

覆蓋的viewDidLayoutSubviews(),並使用該

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    // get pageControl and scroll view from view's subviews 
    let pageControl = view.subviews.filter{ $0 is UIPageControl }.first! as! UIPageControl 
    let scrollView = view.subviews.filter{ $0 is UIScrollView }.first! as! UIScrollView 
    // remove all constraint from view that are tied to pagecontrol 
    let const = view.constraints.filter { $0.firstItem as? NSObject == pageControl || $0.secondItem as? NSObject == pageControl } 
    view.removeConstraints(const) 

    // customize pagecontroll 
    pageControl.translatesAutoresizingMaskIntoConstraints = false 
    pageControl.addConstraint(pageControl.heightAnchor.constraintEqualToConstant(35)) 
    pageControl.backgroundColor = view.backgroundColor 

    // create constraints for pagecontrol 
    let leading = pageControl.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor) 
    let trailing = pageControl.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor) 
    let bottom = pageControl.bottomAnchor.constraintEqualToAnchor(scrollView.topAnchor, constant:8) // add to scrollview not view 

    // pagecontrol constraint to view 
    view.addConstraints([leading, trailing, bottom]) 
    view.bounds.origin.y -= pageControl.bounds.maxY 
} 
+1

這給了一切一個很好的控制,防止增加了一個新的PageControl的。謝謝! – chrilith

2

這裏是一個非常有效的方式來改變PageViewController的默認PageControl的位置,而無需創建一個新的...

extension UIPageViewController { 
override open func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    for subV in self.view.subviews { 
     if type(of: subV).description() == "UIPageControl" { 
      let pos = CGPoint(x: subV.frame.origin.x, y: subV.frame.origin.y - 75 * 2) 
      subV.frame = CGRect(origin: pos, size: subV.frame.size) 
     } 
    } 
} 
} 
0

This is good, and with more change

var pendingIndex = 0; 
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { 
    if completed { 
     pageControl.currentPage = pendingIndex 
    } 
} 

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { 
    let itemController = pendingViewControllers.first as! IntroPageItemViewController 
    pendingIndex = itemController.itemIndex 
} 
6

只是查找的PageControl在PageViewController子類,任何你想要的

override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 
     for subView in view.subviews { 
      if subView is UIPageControl { 
       subView.frame.origin.y = self.view.frame.size.height - 164 
      } 
     } 
    } 
+0

該解決方案效果最佳,對現有代碼設置的干擾最少。 –

0

剛拿到的第一個視圖控制器,並找出在didFinishAnimating索引設置框,位置或:

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { 

    pageControl.currentPage = onboardingViewControllers.index(of: pageViewController.viewControllers!.first!)! 
} 
1

這是我的要求。該版本只在動畫完成時(即,當您到達目標頁面時)更改de指示符。

/** Each page you add to the UIPageViewController holds its index */ 
class Page: UIViewController { 
    var pageIndex = 0 
} 

class MyPageController : UIPageViewController { 

    private let pc = UIPageControl() 
    private var pendingPageIndex = 0 

    // ... add pc to your view, and add Pages ... 

    /** Will transition, so keep the page where it goes */ 
    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) 
    { 
     let controller = pendingViewControllers[0] as! Page 
     pendingPageIndex = controller.pageIndex 
    } 

    /** Did finish the transition, so set the page where was going */ 
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 
    { 
     if (completed) { 
      pc.currentPage = pendingPageIndex 
     } 
    } 
} 
1

斯威夫特4 @揚的回答版本修正了當用戶取消過渡:

首先,創建自定義的PageControl:

let pageControl = UIPageControl() 

你將它添加到查看和定位它,只要你想:

self.view.addSubview(self.pageControl) 
self.pageControl.translatesAutoresizingMaskIntoConstraints = false 
NSLayoutConstraint.activate([ 
    self.pageControl.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor, constant: 43), 
    self.pageControl.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: -33) 
]) 

然後,你需要初始化pageControl:最後

self.pageControl.numberOfPages = self.dataSource.controllers.count 

,你需要實現UIPageViewControllerDelegate,其方法pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:)

func pageViewController(_ pageViewController: UIPageViewController, 
         didFinishAnimating finished: Bool, 
         previousViewControllers: [UIViewController], 
         transitionCompleted completed: Bool) { 
    // this will get you currently presented view controller 
    guard let selectedVC = pageViewController.viewControllers?.first else { return } 

    // and its index in the dataSource's controllers (I'm using force unwrap, since in my case pageViewController contains only view controllers from my dataSource) 
    let selectedIndex = self.dataSource.controllers.index(of: selectedVC)! 
    // and we update the current page in pageControl 
    self.pageControl.currentPage = selectedIndex 
} 

現在與@簡的答案比較,我們採用pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:)更新self.pageControl.currentPage (如上所示),而不是pageViewController(_:willTransitionTo:)。這克服了取消轉換的問題 - pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:)在轉換完成時總是被調用(它也更好地模擬標準頁面控制的行爲)。

最後,除去標準的頁面控制,一定要刪除的UIPageViewControllerDataSourcepresentationCount(for:)presentationIndex(for:)方法實施 - 如果方法實施,該標準網頁控制將提交。

所以,你不希望有這樣的代碼:

func presentationCount(for pageViewController: UIPageViewController) -> Int { 
    return self.dataSource.controllers.count 
} 


func presentationIndex(for pageViewController: UIPageViewController) -> Int { 
    return 0 
} 
0

確保的PageControl添加爲子視圖。 然後在

-(void)viewDidLayoutSubviews { 
     [super viewDidLayoutSubviews]; 

     CGRect frame = self.pageControl.frame; 
     frame.origin.x = self.view.frame.size.width/2 - 
         frame.size.width/2; 
     frame.origin.y = self.view.frame.size.height - 100 ; 
     self.pageControl.numberOfPages = self.tdFeaturePackages.count; 
     self.pageControl.currentPage = self.currentIndex; 
     self.pageControl.frame = frame; 
}