Как сделать нижнюю панель с точками полупрозрачного UIPageViewController?

Я делаю учебник, и я пытаюсь подражать стилю учебника Path так:

http://www.appcoda.com/wp-content/uploads/2013/06/UIPageViewController-Tutorial-Screen.jpg enter image description here

Моя проблема в том, что если установить метод делегата следующим образом:

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
    // The number of items reflected in the page indicator.
    return 5;
}

Затем я получаю эту тупую черную полосу под точками:

http://i.stack.imgur.com/pUEdh.png enter image description here

Есть ли способ сделать этот бар полупрозрачным способом, похожим на настройку UINavigationBar на просвечивание?

Ответ 1

Очень легко заставить его работать. Вам просто нужно только сделать pageviewcontroller выше и поместить файл PageControl в XIB файл. Трюк вначале помещает PageControl на передний план (и все остальные общие элементы управления) в начало и обновляет содержимое PageControl с помощью PageViewController. Вот код:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

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

    self.pageController.dataSource = self;
    // We need to cover all the control by making the frame taller (+ 37)
    [[self.pageController view] setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, [[self view] bounds].size.height + 37)];

    TutorialPageViewController *initialViewController = [self viewControllerAtIndex:0];

    NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];

    [self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

    [self addChildViewController:self.pageController];
    [[self view] addSubview:[self.pageController view]];
    [self.pageController didMoveToParentViewController:self];

    // Bring the common controls to the foreground (they were hidden since the frame is taller)
    [self.view bringSubviewToFront:self.pcDots];
    [self.view bringSubviewToFront:self.btnSkip];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {

    NSUInteger index = [(TutorialPageViewController *)viewController index];

    [self.pcDots setCurrentPage:index];

    if (index == 0) {
        return nil;
    }

    index--;

    return [self viewControllerAtIndex:index];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {

    NSUInteger index = [(TutorialPageViewController *)viewController index];

    [self.pcDots setCurrentPage:index];

    index++;

    if (index == 3) {
        return nil;
    }

    return [self viewControllerAtIndex:index];
}

- (TutorialPageViewController *)viewControllerAtIndex:(NSUInteger)index {

    TutorialPageViewController *childViewController = [[TutorialPageViewController alloc] initWithNibName:@"TutorialPageViewController" bundle:nil];
    childViewController.index = index;

    return childViewController;
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
    // The number of items reflected in the page indicator.
    NSInteger tutorialSteps = 3;
    [self.pcDots setNumberOfPages:tutorialSteps];

    return tutorialSteps;
}

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
    // The selected item reflected in the page indicator.
    return 0;
}

Ответ 2

Такой же эффект может быть достигнут просто путем подкласса UIPageViewController и переопределения viewDidLayoutSubviews следующим образом:

-(void)viewDidLayoutSubviews {
    UIView* v = self.view;
    NSArray* subviews = v.subviews;
    // Confirm that the view has the exact expected structure.
    // If you add any custom subviews, you will want to remove this check.
    if( [subviews count] == 2 ) {
        UIScrollView* sv = nil;
        UIPageControl* pc = nil;
        for( UIView* t in subviews ) {
            if( [t isKindOfClass:[UIScrollView class]] ) {
                sv = (UIScrollView*)t;
            } else if( [t isKindOfClass:[UIPageControl class]] ) {
                pc = (UIPageControl*)t;
            }
        }
        if( sv != nil && pc != nil ) {
            // expand scroll view to fit entire view
            sv.frame = v.bounds;
            // put page control in front
            [v bringSubviewToFront:pc];
        }
    }
    [super viewDidLayoutSubviews];
}

Тогда нет необходимости поддерживать отдельный UIPageControl и т.д.

Ответ 3

Здесь преобразование решения Zerotool в Swift 2.1, хотя, возможно, более элегантный способ его написать:

override func viewDidLayoutSubviews() {
    var scrollView: UIScrollView?
    var pageControl: UIPageControl?

    // If you add any custom subviews, you will want to remove this check.
    if (self.view.subviews.count == 2) {
        for view in self.view.subviews {
            if (view.isKindOfClass(UIScrollView)) {
                scrollView = view as? UIScrollView
            } else if (view.isKindOfClass(UIPageControl)) {
                pageControl = view as? UIPageControl
            }
        }
    }

    if let scrollView = scrollView {
        if let pageControl = pageControl {
            scrollView.frame = self.view.bounds
            self.view.bringSubviewToFront(pageControl)
        }
    }

    super.viewDidLayoutSubviews()
}

Ответ 4

Swift 3 snippet

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let scrollView = view.subviews.filter({ $0 is UIScrollView }).first,
        let pageControl = view.subviews.filter({ $0 is UIPageControl }).first {
        scrollView.frame = view.bounds
        view.bringSubview(toFront:pageControl)
    }
}

Ответ 5

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

Ответ 6

Вы можете просто настроить альфа UIPageViewController UIPageControl.

Сначала вы должны получить его из UIPageViewController следующим образом:

- (UIPageControl *)getPageControlForPageViewController:(UIPageViewController *)pageViewController {
      for (UIView *subview in self.pageViewController.view.subviews) {
        if ([subview isKindOfClass:[UIPageControl class]]) {
          return (UIPageControl *) subview;
        }
      }

      return nil;
    }

Затем используйте функцию. Я создал свойство на моем ViewController с именем childPageControl. Дайте UIPageViewController UIPageControl:

self.childPageControl = [self getPageControlForPageViewController:self.pageViewController];

Затем вы можете отрегулировать альфу, чтобы получить полупрозрачный эффект:

self.childPageControl.alpha = .5;

Вы очень ограничены тем, что можете сделать, чтобы повлиять на UIPageViewController UIPageControl, но вы можете хотя бы добиться этого с минимальными усилиями.

Ответ 7

Небольшой взлом, который я нашел сегодня.

Пожалуйста, смотрите код ниже.

введите описание изображения здесь

self.pageController.dataSource = self;
    CGRect rect = [self.view bounds];
    rect.size.height+=37;
    [[self.pageController view] setFrame:rect];
        NSArray *subviews = self.pageController.view.subviews;
        UIPageControl *thisControl = nil;
        for (int i=0; i<[subviews count]; i++) {
            if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]]) {
                thisControl = (UIPageControl *)[subviews objectAtIndex:i];
            }
        }

        UIView *tempview = [[UIView alloc] initWithFrame:CGRectMake(0, -30, 320, 40)];
        [tempview addSubview:thisControl];
        thisControl.pageIndicatorTintColor = [UIColor lightGrayColor];
        thisControl.currentPageIndicatorTintColor = [UIColor greenColor];
        [self.view addSubview:tempview];

Ответ 8

этот код находится в Swift Добавьте в свой UIPageViewController следующее:

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

    for view in self.view.subviews {
        if view.isKindOfClass(UIScrollView) {
            view.frame = UIScreen.mainScreen().bounds
        } else if view.isKindOfClass(UIPageControl) {
            view.backgroundColor = UIColor.clearColor()
        }
    }
}

Ответ 9

Я решаю использовать этот код:

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.


self.namesImage = @[@"page1.png", @"page2.png", @"page3.png", @"page4.png"];

self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
self.pageViewController.dataSource = self;


TutorialContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = @[startingViewController];

[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];


[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];

[[UIPageControl appearance] setPageIndicatorTintColor:[UIColor grayColor]];
[[UIPageControl appearance] setCurrentPageIndicatorTintColor:[UIColor whiteColor]];
[[UIPageControl appearance] setBackgroundColor: [[UIColor blackColor] colorWithAlphaComponent:0.1f]];
[[UIPageControl appearance] setOpaque:YES];

}

Ответ 10

Я нашел другой рабочий стол, который мне подходит лучше.

Я повторно использую код, указанный zerotool, чтобы получить UIPageControl (var called pageControl) и UIScrollView (var called pageView) используемый UIPageViewController.

Как только это делается в viewDidLoad, я просто запрещаю подзаголовок клипа pageView и позволяю содержимому больше распространяться под UIPageControl.

Страница "Контроль" находится под страничным экраном, поэтому мы должны вручную сделать это впереди.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    if(
       [[[self view] subviews] count] == 2
       )
    {
        UIScrollView* pageView = nil;
        UIPageControl* pageControl = nil;

        UIView* selfView = self.view;
        NSArray* subviews = selfView.subviews;

        for( NSInteger i = 0 ; i < subviews.count && ( pageView == nil || pageControl == nil ) ; i++ )
        {
            UIView* t = subviews[i];
            if( [t isKindOfClass:[UIScrollView class]] )
            {
                pageView = (UIScrollView*)t;
            }
            else if( [t isKindOfClass:[UIPageControl class]] )
            {
                pageControl = (UIPageControl*)t;
            }
        }

        if( pageView != nil && pageControl != nil )
        {
            [pageView setClipsToBounds:NO];
            [selfView bringSubviewToFront:pageControl];
        }
    }
}

Как только я получаю свой pageView, покрывающий пространство, занимаемое pageControl, но под управлением pageControl, мне просто нужно настроить использование файла nib для каждого viewController, отображаемого как страница:

  • базовый вид не должен содержать клип
  • первое и единственное подчинение:
    • должно быть ограничено, чтобы установить дно в -37 (или больше, если вам нужно, но 37 - размер pageControl) снизу надстройки
    • должен закрепить контент

Ответ 11

Я хотел сделать аналогичный эффект в приложении, над которым я работал, - я использовал UIPageViewController с отдельным UIPageControl.

Это позволяет размещать UIPageControl в любом месте в представлении, в том числе поверх UIPageViewController, и поддерживать постоянную актуальную страницу страницы с помощью метода делегирования UIPageViewController:

- (void)pageViewController:(UIPageViewController *)pageViewController
        didFinishAnimating:(BOOL)finished
   previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers
       transitionCompleted:(BOOL)completed {
    if (completed) {
        self.pageControl.currentPage = [self.pageViewControllers indexOfObject:pageViewController.viewControllers.firstObject];
    }
}

Не нужно проходить иерархию подкадров, пытаясь найти внутренний элемент управления UIPageViewController, а также не изменять размер внутреннего содержимого прокрутки.

Надеюсь, что это поможет.