Можем ли мы настроить индикатор страницы в UIPageViewController?

Теперь это белые точки на черном фоне. А если я хочу, чтобы это были черные точки с белым фоном?

- (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.

person Septiadi Agus    schedule 04.07.2013    source источник
comment
Отсутствие хуков настройки для UIPageControl UIPageViewController является настоящей проблемой. По-видимому, вы не можете изменить его положение или изменить цвет. Вы также не можете заставить его скрыться, если есть только одна страница. На самом деле, UIPageViewController — это довольно паршивый класс во всех отношениях — плохо работает с авторазметкой, создает всевозможные волшебные подпредставления и т. д. К сожалению, разбивка на страницы с помощью UIScrollView также проблематична, поскольку открывает двери для проблем с управлением памятью, когда вы У меня много страниц.   -  person sirvine    schedule 09.07.2013
comment
raywenderlich.com/21703/user-interface-customization-in- iOS-6   -  person yazh    schedule 23.01.2015
comment
У меня есть решение для этого в Swift 4. Пожалуйста, проверьте мой ответ ниже.   -  person wsgeorge    schedule 02.06.2018


Ответы (11)


Я не верю, что вы можете манипулировать элементом управления страницей UIPageViewController. Мое решение:

У меня есть «корневой» UIViewController, который является UIPageViewControllerDelegate и UIPageViewControllerDataSource.

На этом корневом контроллере представления у меня есть @property (strong, nonatomic) IBOutlet UIPageControl *pageControl. В соответствующем наконечнике раскадровки я добавляю 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 превышать размер экрана, так что собственный элемент управления страницей больше не виден. Мое приложение только портретное, только для iPhone, поэтому я немного легко отделался здесь. Если вам нужно обрабатывать повороты, вам придется найти способ сохранить этот собственный элемент управления страницей за пределами экрана.Я пытался использовать автоматическую компоновку, но UIPageViewController создает набор волшебных представлений, которые имеют кучу ограничений маски автомакета, которые я не мог найти способ переопределить.)

В любом случае... затем я добавляю дополнительный метод делегата 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 Apple для этого класса не совсем подходит для элегантности.

person sirvine    schedule 09.07.2013
comment
Нет необходимости изменять размер рамки просмотра. Если вы не реализуете методы индикатора страницы источника данных, собственный элемент управления страницей не отображается, а дополнительное поле в нижней части представления не добавляется. - person Paul Linsay; 29.07.2015
comment
Спасибо большое. Этот контроллер просмотра страниц решил мою проблему. В моем случае мне не нужны self.view.gestureRecognizers = self.pageViewController.gestureRecognizers; А также я установил pageControl.userInteractionEnabled = NO; поэтому, когда мы прокручиваем pageControl, он не обновляет атрибут currentPage, но pageViewController не меняет контроллер представления. - person felixwcf; 12.12.2016

Вы можете использовать UIAppearance для изменения цвета UIPageControl. Попробуйте это в функции didFinishLaunchingWithOptions вашего AppDelegate.

- (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];

Теперь только UIPageControl объектов, содержащихся в MyViewController, будут адаптировать этот стиль.

Спасибо, Майк и Шингу!

EDIT: Если вы видите черный фон вокруг UIPageControl в нижней части экрана, это связано с цветом фона вашего UIPageViewController, а не UIPageControl. Вы можете изменить этот цвет следующим образом:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blueColor]; //Set it to whatever you like
}
person Yas Tabasam    schedule 23.08.2013
comment
Вы можете пойти дальше и использовать [UIPageControl appearenceInContainer:[MyViewController class], nil], если хотите избежать глобального изменения элементов управления страницей. - person Mike Abdullah; 01.10.2013
comment
[Внешний вид UIPageControlWhenContainedIn: [Класс MyViewController], ноль] должен быть правильным - person Shingoo; 13.10.2013
comment
Мне нравится этот ответ. Гораздо лаконичнее. - person Kyle Clegg; 16.10.2013
comment
Вместо делегата приложения вы можете добавить его в свой суперконтроллер PageViewControllers. Но +1 за это, гораздо лучшее решение, чем другие, которые я нашел. - person GoodSp33d; 04.10.2014
comment
@Yas Я думаю, что цвет фона PageControl связан с backGroundColor контроллера представления, потому что у меня есть imageViews в pageviewController, а PageControl присутствует над этим изображением, и установка свойства backGroundColor не меняет цвет PageControl. - person meteors; 23.04.2015
comment
Спасибо за ответ. Это правда, что черный цвет — это фон UIPageViewController. Однако я не могу установить чистый цвет. Если я установлю его на чистый цвет, фон станет черным. Скажите, пожалуйста, есть ли другой способ добиться этого, используя оттенок или альфу или что-то в этом роде.... - person okysabeni; 07.05.2015
comment
Можем ли мы также изменить форму управления страницами? - person Priyal; 27.12.2016

На самом деле вы можете получить его и сохранить локально в своем собственном свойстве в одном из вызовов делегата.

Поместите этот код в свой делегат, чтобы получить доступ к UIPageControl внутри UIPageViewController:

- (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];
}
person Yariv Nissim    schedule 11.10.2013

Вы можете рекурсивно искать его в своих подвидах

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

меня устраивает

person CyberKid    schedule 10.04.2014
comment
Я пробовал что-то подобное, но так и не нашел подвид, который был UIPageControl. Пожалуйста, смотрите мой ответ ниже о том, что я сделал. - person wsgeorge; 02.06.2018

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

Это изменит внешний вид только для «MyViewController». Если вы хотите иметь разные цвета в разных индикаторах страниц в одном и том же представлении, вам необходимо создать разные подпредставления и настроить их индивидуально.

person Shingoo    schedule 13.10.2013

Вот что я сделал в 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 в этом блоке, вы сможете настроить цвета его индикаторов.

person wsgeorge    schedule 02.06.2018

Если вы используете «автоматически сгенерированный» индикатор страницы, созданный UIPageViewController, я думаю, что вы не сможете его настроить. Единственный способ сделать это — добавить дополнительный PageControl, либо предоставленный Apple, либо пользовательский, как предложил @Maschel.

person Heckscheibe    schedule 04.07.2013

Его можно настроить через внешний вид. Вы можете сделать это в 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];
person Zeezer    schedule 26.11.2013

Этот отлично работает для пользовательского изображения

self.pageControl.pageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"page_indicater"]];

self.pageControl.currentPageIndicatorTintColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"page_indicater_selection"]];
person Gurumoorthy Arumugam    schedule 03.01.2017

Вы можете использовать SMPageControl: Github. Он работает так же, как UIPageControl, но с большими возможностями настройки.

person Maschel    schedule 04.07.2013
comment
Обратите внимание, что это работает как UIPageControl, а не как UIPageController. Я отредактировал ответ, чтобы исправить это, но мое редактирование было отклонено. Не уверен, почему. - person Stewart Macdonald; 17.06.2015
comment
Поскольку вопрос ищет ответы, которые могут работать с источником данных, предоставленным UIPageViewController - person Walter Martin Vargas-Pena; 05.02.2016

Вы можете легко получить доступ к UIPageViewController pageControl, определив вычисляемое свойство следующим образом:

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
}

Очевидное предостережение: если Apple когда-либо решит изменить иерархию представлений UIPageViewController, это перестанет работать.

person boliva    schedule 27.09.2018