我们能否在UIPageViewController中自定义页面指示器?

47

现在是白色点,黑色背景。如果我想要黑色点,白色背景怎么办?

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
{
    return _imageArrays.count;
}// The number of items reflected in the page indicator.
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
{
    return self.intCurrentIndex;
}// The selected item reflected in the page indicator.

6
UIPageViewController的UIPageControl缺乏自定义挂钩是一个真正的问题。 显然,您无法重新定位它或更改颜色。 您也无法告诉它在只有一页时隐藏。 实际上,UIPageViewController是一个相当糟糕的类 - 它不与自动布局很好地配合,创建各种神奇的子视图等。 不幸的是,使用UIScrollView进行分页也存在问题,因为当您有大量页面时,这会打开内存管理问题的大门。 - sirvine
http://www.raywenderlich.com/21703/user-interface-customization-in-ios-6 - yazh
我在Swift 4中有一个解决方案,请查看下面的回答。 - wsgeorge
11个回答

131

你可以使用UIAppearance来更改UIPageControl的颜色。在你的AppDelegate的didFinishLaunchingWithOptions函数中尝试一下这个。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UIPageControl *pageControl = [UIPageControl appearance];
    pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
    pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
    pageControl.backgroundColor = [UIColor blueColor];

    return YES;
}

编辑:

要仅将样式应用于特定的视图控制器,请使用appearanceWhenContainedIn,如下所示:

UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];

现在,只有包含在MyViewController中的UIPageControl对象将适应此样式。

谢谢Mike和Shingoo!

编辑: 如果在屏幕底部看到UIPageControl周围有黑色背景,则是由于您的UIPageViewController的背景颜色而不是UIPageControl。 您可以按以下方式更改此颜色:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blueColor]; //Set it to whatever you like
}

12
如果想避免全局改变页面控件,可以进一步使用 [UIPageControl appearanceInContainer:[MyViewController class], nil] - Mike Abdullah
3
[UIPageControl appearanceWhenContainedIn:[MyViewController class], nil] 应该是正确的。 - Shingoo
2
我喜欢这个答案。更加简洁。 - Kyle Clegg
你可以将它添加到你的PageViewControllers超级控制器中,而不是AppDelegate。但是这个解决方案比我找到的其他解决方案都要好得多,加1! - GoodSp33d
@Yas,我认为PageControl的背景颜色是由视图控制器的backGroundColor属性决定的,因为我在pageViewController中有一些imageView,并且PageControl位于这些图像之上,设置backGroundColor属性并不会改变PageControl的颜色。 - meteors
显示剩余2条评论

35

我不相信你可以操作UIPageViewController的页面控制。我的解决方法:

我有一个作为UIPageViewControllerDelegate和UIPageViewControllerDataSource的“根”UIViewController。

在这个根视图控制器上,我有@property (strong, nonatomic) IBOutlet UIPageControl *pageControl。在对应的故事板nib中,我添加了一个UIPageControl,将其定位,并选中“单页隐藏”。如果需要,我还可以更改颜色。

然后,在根视图控制器的viewDidLoad中,我添加了以下内容:self.pageControl.numberOfPages = [self.features count]

我的根视图控制器还有一个@property (strong, nonatomic) UIPageViewController *pageViewController。实现中:

self.pageViewController = [[UIPageViewController alloc]
          initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll 
            navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal 
                          options:nil];


self.pageViewController.delegate = self;
DataViewController *startingViewController = [self viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = @[startingViewController];
[self.pageViewController setViewControllers:viewControllers
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:NO
                                 completion:NULL];
self.pageViewController.dataSource = self;      
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.pageViewController.view.frame = CGRectMake(0.0, 0.0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height + 10.0);
[self.pageViewController didMoveToParentViewController:self];
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

总之,然后我添加了一个额外的UIPageViewController委托方法来将我的新非本机UIPageControl更改为当前选择的页面:

- (void)pageViewController:(UIPageViewController *)viewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
  if (!completed){return;}

  // Find index of current page
  DataViewController *currentViewController = (DataViewController *)[self.pageViewController.viewControllers lastObject];
  NSUInteger indexOfCurrentPage = [self indexOfViewController:currentViewController];
  self.pageControl.currentPage = indexOfCurrentPage;
}

我希望更漂亮些,但苹果的这个类的API不太容易实现优雅。


5
不需要调整视图框架大小。如果您不实现数据源页面指示方法,则原生页面控件不会出现,视图底部的额外边距也不会添加。 - Paul Linsay
非常感谢。这个页面视图控制器解决了我的问题。 对于我的情况,我不需要self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; 而且,我设置了pageControl.userInteractionEnabled = NO; 所以当我们在pageControl中滑动时,它不会更新currentPage属性,但是pageViewController并没有改变视图控制器。 - felixwcf

7

在委托方法中,您实际上可以获取UIPageViewController中的UIPageControl并将其存储到自己的属性中。

将此代码放置在您的委托方法中,以访问 UIPageViewController 中的 UIPageControl:

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    [self setupPageControlAppearance];
    return kPageCount;
}

- (void)setupPageControlAppearance
{
    UIPageControl * pageControl = [[self.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(class = %@)", [UIPageControl class]]] lastObject];
    pageControl.pageIndicatorTintColor = [UIColor grayColor];
    pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
}

4
你可以在子视图中递归搜索它。
- (void)findAndConfigurePageControlInView:(UIView *)view
{
    for (UIView *subview in view.subviews) {
        if ([subview isKindOfClass:[UIPageControl class]]) {
            UIPageControl * pageControl = (UIPageControl *)subview;
            //customize here
            pageControl.hidesForSinglePage = YES;
            break;
        } else {
            [self findAndConfigurePageControlInView:subview];
        }
    }
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
    [self findAndConfigurePageControlInView:self.view];
    return self.promotionsVCs.count;
}

这对我有效


我尝试过类似的事情,但我从来没有找到一个子视图是UIPageControl的方法。请查看下面我的答案,了解我做了什么。 - wsgeorge

3

以下是我在Swift 4中所做的。我首先尝试了类似的答案,放在viewDidLoad中,但最终这个代码片段才起作用。这个相同的代码片段被用来回答类似的SO问题。

    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    for view in self.view.subviews{
        if view is UIPageControl{
            (view as! UIPageControl).currentPageIndicatorTintColor = .yellow
            }
        }
    }

一旦您在此块中有了UIPageControl,您就可以自定义其指示器的颜色。


2
UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
pageControl.currentPageIndicatorTintColor = [UIColor redColor];
pageControl.backgroundColor = [UIColor blackColor];

这将仅更改“MyViewController”的外观。如果您希望在同一视图中的不同页面指示器中具有不同的颜色,则必须创建不同的子视图并单独自定义它们。


1
可以通过外观进行自定义。您可以在AppDelegate中按如下方式进行操作。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   UIPageControl *pageControl = [UIPageControl appearance];
   pageControl.pageIndicatorTintColor = [UIColor whiteColor];
   pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
   pageControl.backgroundColor = [UIColor lightGrayColor];

   return YES;
}

如果您只想针对某个视图控制器执行此操作,请使用以下内容替换pageControl。
UIPageControl *pageControl = [UIPageControl appearanceWhenContainedIn:[MyViewController class], nil];

1
如果您使用由UIPageViewController创建的“自动生成”的页面指示器,我认为您无法自定义它。唯一的解决方法是添加额外的PageControl,可以选择Apple提供的或像@Maschel建议的自定义的PageControl。

1
这个对自定义图像完美地运作。
self.pageControl.pageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"page_indicater"]];

self.pageControl.currentPageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"page_indicater_selection"]];

0
你可以通过定义一个计算属性来轻松访问UIPageViewControllerpageControl,像这样:
var pageControl: UIPageControl? {
    for subview in view.subviews {
        if let pageControl = subview as? UIPageControl {
            return pageControl
        }
    }
    return nil
}

然后像这样自定义它以适应您的需求:

override func viewDidLoad() {
    super.viewDidLoad()
    pageControl?.backgroundColor = .white
    pageControl?.pageIndicatorTintColor = .red
    pageControl?.currentPageIndicatorTintColor = .blue
}

显而易见的警告:如果苹果公司决定更改UIPageViewController视图层次结构,则此方法将停止工作。


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