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

时间:2015-09-28 12:13:42

标签: ios uipageviewcontroller uipagecontrol

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

14 个答案:

答案 0 :(得分:34)

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

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;
 }

答案 1 :(得分: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
}

答案 2 :(得分: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;
    }
}

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

希望它有所帮助!

答案 3 :(得分:7)

只需在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
            }
        }
    }

答案 4 :(得分: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的大小以掩盖底部差距:

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

答案 5 :(得分:3)

当用户取消转换时,使用修复错误的@ Jan的回答

Swift 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
}

现在与@ Jan的答案相比,我们使用self.pageControl.currentPage(如上所示)更新pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:),而不是pageViewController(_:willTransitionTo:)。这克服了取消转换的问题 - 在转换完成时始终调用pageViewController(_:didFinishAnimating:previousViewControllers:transitionCompleted:)(它也更好地模仿标准页面控制的行为)。

最后,要删除标准页面控件,请务必删除presentationCount(for:)的{​​{1}}和presentationIndex(for:)方法的实现 - 如果方法已实现,则标准页面控件将是呈现。

所以,你不希望在你的代码中有这个:

UIPageViewControllerDataSource

答案 6 :(得分: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并委托pageView

然后删除

func presentationCountForPageViewController(
    pageViewController: UIPageViewController
) -> Int

func presentationIndexForPageViewController(
    pageViewController: UIPageViewController
) -> Int

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

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

答案 7 :(得分: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)
        }
    }
}
}

答案 8 :(得分: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
        }
    }
}

答案 9 :(得分: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
}

答案 10 :(得分:0)

确保将pageControl添加为子视图。 然后在

UserID='$_SESSION['currentUserID']'

答案 11 :(得分:0)

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    for view in self.view.subviews{
        if view is UIScrollView{
            view.frame = UIScreen.main.bounds
        }
        else if view is UIPageControl {
            view.backgroundColor = UIColor.clear
            view.frame.origin.y = self.view.frame.size.height - 75
        }
    }
}

答案 12 :(得分:0)

Swift 5和iOS 13.5(具有手动布局)

下面的示例使用自定义的UIPageControl,它位于UIPageViewController的底部中心位置。要使用该代码,请将MemberProfilePhotoViewController替换为您用作页面的视图控制器类型。

快速笔记

  1. 您必须在numberOfPages上设置pageControl属性。
  2. 要设置pageControl的大小,可以使用pageControl.size(forNumberOfPages: count)
  3. 确保删除presentationCount(...)presentationIndex(...)以删除默认页面控件。
  4. 使用UIPageViewControllerDelegate的{​​{1}}似乎是更新didFinishAnimating的更好时机。

代码

pageControl.currentPage

答案 13 :(得分:-1)

只需获取第一个视图控制器并找出didFinishAnimating中的索引:

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

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