如何在iOS> = 8.0中更改UIPageControl的位置?

Ngu*_*Thu 16 uipagecontrol ios uipageviewcontroller

我有一个简单的UIPageViewController,它在页面底部显示默认的UIPageControl.我想知道是否可以修改UIPageControl的位置,例如在屏幕顶部而不是底部.我一直在环顾四周,只发现旧讨论说我需要创建自己的UIPageControl.这对iOS8和9来说更简单吗?谢谢.

Jan*_*Jan 35

是的,您可以为此添加自定义页面控制器.

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];
Run Code Online (Sandbox Code Playgroud)

然后删除

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
Run Code Online (Sandbox Code Playgroud)

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
Run Code Online (Sandbox Code Playgroud)

然后添加另一个委托方法:

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

  • 这是很好的描述,但不完全有效.正如Jiri指出的那样,如果用户滑动部分方式,则会中断,但取消(因为它更新页面控件,就好像页面转换实际发生一样).我使用的解决方案是更新委托didFinishAnimating中的页面控件.此行为与iOS主屏幕上的Apple行为相匹配(转换完成后更新页面控件) (3认同)

Cja*_*jay 8

覆盖pageviewcontroller的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
}
Run Code Online (Sandbox Code Playgroud)

  • 这样可以很好地控制所有内容,并防止添加新的pageControl.谢谢! (2认同)

Tru*_*han 8

只需在PageViewController子类中查找PageControl并设置框架,位置或任何您想要的内容

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        for subView in view.subviews {
            if  subView is  UIPageControl {
                subView.frame.origin.y = self.view.frame.size.height - 164
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


Jir*_*cak 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是因为如果不这样做,如果您稍微移动页面控件,它将返回到上一个位置 - 但页面控件将显示不同的页面.

希望能帮助到你!


Mil*_*sáľ 5

Swift 4 version of @Jan's answer with fixed bug when the user cancels transition:

First, you create custom pageControl:

let pageControl = UIPageControl()
Run Code Online (Sandbox Code Playgroud)

You add it to the view and position it as you want:

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)
])
Run Code Online (Sandbox Code Playgroud)

Then you need to initialize the pageControl:

self.pageControl.numberOfPages = self.dataSource.controllers.count
Run Code Online (Sandbox Code Playgroud)

Finally, you need to implement UIPageViewControllerDelegate, and its method 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
}
Run Code Online (Sandbox Code Playgroud)

Now in comparison with @Jan's answer, we update self.pageControl.currentPage using pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:) (shown above), instead of pageViewController(_:willTransitionTo:). This overcomes the problem of cancelled transition - pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:) is called always when a transition was completed (it also better mimics the behavior of standard page control).

Finally, to remove the standard page control, be sure to remove implementation of presentationCount(for:) and presentationIndex(for:) methods of the UIPageViewControllerDataSource - if the methods are implemented, the standard page control will be presented.

So, you do NOT want to have this in your code:

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


func presentationIndex(for pageViewController: UIPageViewController) -> Int {
    return 0
}
Run Code Online (Sandbox Code Playgroud)