Как поместить элемент UIPageControl поверх скользящих страниц в UIPageViewController?



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



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



Как можно поместить элемент управления поверх просмотры таким образом, просмотры страниц являются полноэкранными (например, с изображением), чтобы пользователь мог видеть представления под фиксированным элементом управления?



Я приложил пример скриншот-кредиты к AppCoda и путь:



enter image description here

710   7  

7 ответов:

после дальнейшего расследования и поиска Я нашел решение, также на stackoverflow.

ключ-это следующее сообщение для отправки на пользовательский UIPageControl элемент:

[self.view bringSubviewToFront:self.pageControl];

учебник AppCoda является основой для этого решения:

добавить UIPageControl элемент сверху RootViewController - контроллер вида со стрелкой.

создать соответствующие IBOutlet элемент ViewController.m.

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

[self.view bringSubviewToFront:self.pageControl];

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

- (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    // ...
    index--;
    [self.pageControl setCurrentPage:index];

    return [self viewControllerAtIndex:index];
}

- (UIPageViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    // ...
    index++;
    [self.pageControl setCurrentPage:index];

    // ...
    return [self viewControllerAtIndex:index];
}

У меня не было представителя, чтобы прокомментировать ответ, который вызвал это, но мне это очень нравится. Я улучшил код и преобразовал его в swift для нижеприведенного подкласса UIPageViewController:

class UIPageViewControllerWithOverlayIndicator: UIPageViewController {
    override func viewDidLayoutSubviews() {
        for subView in self.view.subviews as! [UIView] {
            if subView is UIScrollView {
                subView.frame = self.view.bounds
            } else if subView is UIPageControl {
                self.view.bringSubviewToFront(subView)
            }
        }
        super.viewDidLayoutSubviews()
    }
}

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

sn3ek ваш ответ получил меня большую часть пути туда. Я не устанавливал текущую страницу с помощью методы.

я ViewController also представитель UIPageViewController. Затем я установил PageControl ' s CurrentPage в этом методе. Используя pageIndex утверждал, что я ContentViewController упоминание в оригинальной статье.

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
  APPChildViewController *currentViewController = pageViewController.viewControllers[0];
  [self.pageControl setCurrentPage:currentViewController.pageIndex];
}

не забудьте добавить это viewDidLoad

self.pageViewController.delegate = self;

чтобы следить за комментарием PropellerHead интерфейс для ViewController будет имейте форму

@interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate>

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

-(void)viewDidLayoutSubviews {
    UIView* v = self.view;
    NSArray* subviews = v.subviews;
    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 и тому подобное.

вот ответ RxSwift/RxCocoa, который я собрал, посмотрев на другие ответы.

let pages = Variable<[UIViewController]>([])
let currentPageIndex = Variable<Int>(0)
let pendingPageIndex = Variable<(Int, Bool)>(0, false)

let db = DisposeBag()

override func viewDidLoad() {
    super.viewDidLoad()
    pendingPageIndex
        .asDriver()
        .filter { .1 }
        .map { .0 }
        .drive(currentPageIndex)
        .addDisposableTo(db)

    currentPageIndex.asDriver()
        .drive(pageControl.rx.currentPage)
        .addDisposableTo(db)
}

func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
    if let index = pages.value.index(of: pendingViewControllers.first!) {
        pendingPageIndex.value = (index, false)
    }
}

func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    pendingPageIndex.value = (pendingPageIndex.value.0, completed)
}

вы должны реализовать пользовательский UIPageControl и добавить его на вид. Как уже говорили другие, view.bringSubviewToFront(pageControl) должен быть вызван.

у меня есть пример контроллера вида со всем кодом при настройке пользовательского UIPageControl (в раскадровке) с UIPageViewController

есть 2 метода, которые необходимо реализовать, чтобы установить индикатор текущей страницы.

func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
    pendingIndex = pages.indexOf(pendingViewControllers.first!)
}

func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    if completed {
        currentIndex = pendingIndex
        if let index = currentIndex {
            pageControl.currentPage = index
        }
    }
}

вот ответ Swifty 2 очень сильно основан на ответе @zerotool выше. Просто подкласс UIPageViewController, а затем добавить это переопределение, чтобы найти scrollview и изменить его размер. Затем возьмите элемент управления страницей и переместите его в начало всего остального. Вам также необходимо установить цвет фона элементов управления страниц, чтобы очистить. Эти последние две строки могут войти в делегат вашего приложения.

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    var sv:UIScrollView?
    var pc:UIPageControl?

    for v in self.view.subviews{

        if v.isKindOfClass(UIScrollView) {

            sv = v as? UIScrollView

        }else if v.isKindOfClass(UIPageControl) {

            pc = v as? UIPageControl
        }
    }

    if let newSv = sv {

        newSv.frame = self.view.bounds
    }

    if let newPc = pc {

        self.view.bringSubviewToFront(newPc)
    }
}

let pageControlAppearance = UIPageControl.appearance()
pageControlAppearance.backgroundColor = UIColor.clearColor()

кстати-я не замечаю никаких бесконечных циклов, как упоминалось выше.

Comments

    Ничего не найдено.