2014-01-10 14 views
56

In Bezug auf diese tutorial by AppCoda about how to implement a app with UIPageViewController Ich möchte ein benutzerdefiniertes Seitensteuerelement oben auf den Seiten statt unten verwenden.Wie setze ich das UIPageControl Element auf die verschiebbaren Seiten innerhalb eines UIPageViewControllers?

Wenn ich einfach ein Seitensteuerelement auf die einzelnen Ansichten setze, die angezeigt werden, ist das logische Ergebnis, dass die Steuerelemente mit der Seitenansicht vom Bildschirm wegrollen.

Wie ist es möglich, das Steuerelement über den Ansichten zu platzieren, so dass die Seitenansichten Vollbild sind (wie bei einem Bild), sodass der Benutzer die Ansichten unter dem festen Steuerelement sehen kann?

ich ein Beispiel-Screenshot angehängt - Kredite an AppCoda and Path:

enter image description here

Antwort

49

Nach einer weiteren Untersuchung und I found a solution, auch auf Stackoverflow zu suchen.

Der Schlüssel ist die folgende Meldung zu einem benutzerdefinierten UIPageControl Elemente senden:

[self.view bringSubviewToFront:self.pageControl]; 

The AppCoda tutorial is the foundation for this solution: auf der Oberseite der RootViewController

hinzufügen UIPageControl Element - View-Controller mit dem Pfeil.

Erstellen Sie ein verwandtes IBOutlet Element in Ihrem ViewController.m.

In der Methode viewDidLoad sollten Sie dann den folgenden Code als letzte Methode hinzufügen, die Sie nach dem Hinzufügen aller Unteransichten aufrufen.

[self.view bringSubviewToFront:self.pageControl]; 

die aktuelle Seite zuweisen auf der pageindex des aktuellen Inhalts Ansicht basierend Sie die folgenden auf die UIPageViewControllerDataSource Methoden hinzufügen:

- (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]; 
} 
+2

seltsam für mich, das Setzen der PageControl-Seite vor dem Inkrementieren/Dekrementieren des Index gearbeitet. Der ViewController, den ich von der Methode bekommen habe, war der des neuen View-Controllers und nicht der des vorherigen. – Gokul

+0

Das ist überhaupt nicht seltsam; es wird erwartet. Diese Methoden werden auf dem * aktuellen * View-Controller aufgerufen, um zu bestimmen, was als nächstes kommt. –

+0

@ sn3ek So erstellen Sie ein verwandtes IBOutlet-Element. – VJVJ

27

sn3ek Ihre Antwort hat mich die meisten der Weg dorthin. Ich habe die aktuelle Seite jedoch nicht mit den Methoden viewControllerCreation festgelegt.

Ich machte meine der Delegierte der UIPageViewController. Dann setze ich die PageControl 's CurrentPage in dieser Methode. Unter Verwendung der pageIndex beibehalten ich bin die Erwähnung im ursprünglichen Artikel.

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

vergessen Sie nicht, dies für die ViewController zu viewDidLoad

self.pageViewController.delegate = self; 

Um Follow-up auf Propellerhead Kommentar die Schnittstelle hinzuzufügen, wird das Formular

@interface ViewController : UIViewController <UIPageViewControllerDataSource, UIPageViewControllerDelegate> 
+2

Nur um klar zu sein. Der Delegat von UIPageViewController ist UIPageViewControllerDelegate, also sieht die Schnittstelle Ihres ViewControllers ungefähr so ​​aus: '' @ @interface ViewController: UIViewController '' ' – PropellerHead

+1

Das ist richtig. – Coderdad

2

die gleiche Wirkung haben kann einfach durch Unterklassifizieren von UIPageViewController und Überschreiben von viewDidLayoutSubviews wie folgt erreicht:

Dann muss kein separates UIPageControl und ähnliches gepflegt werden.

+2

Ich mochte diese Antwort eigentlich. Es hat gut funktioniert. Bis ich ein iPhone 4S mit iOS 7.1 aufgesetzt habe. An diesem Punkt ging es unendlich. Nicht sicher warum, aber Vorsicht. –

48

Ich hatte nicht den Vertreter, um die Antwort zu kommentieren, die dieses verursachte, aber ich mag es wirklich. Ich verbesserte den Code und konvertiert es zu raschen für die unter Unterklasse von 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() 
    } 
} 

reinigen und es funktioniert gut. Keine Notwendigkeit, etwas beizubehalten. Machen Sie Ihren Page View-Controller zu einer Instanz dieser Klasse im Storyboard, oder lassen Sie stattdessen Ihre eigene Page-View-Controller-Klasse von dieser Klasse erben.

+0

Wenn ich diese für Schleife in ViewDidLoad setze, kann ich die scrollView aber nicht die UIPageControl Ansicht finden. Fehle ich etwas? – Hakim

+0

@Hakim vielleicht der Controller fehlt der UIPageViewController Typ? Es ist schwer, ohne ein Beispiel für die genaue Situation zu sagen. –

+1

Ich werde dies nur für wie vielseitige und nützliche das ist. Vielen Dank !! –

0

Hier ist die Antwort Swifty 2, die sehr auf der obigen Antwort von @ zerotool basiert. Einfach Unterklasse UIPageViewController und dann diese Überschreibung hinzufügen, um die scrollview zu finden und die Größe zu ändern. Dann nehmen Sie die Seitensteuerung und verschieben Sie sie an den Anfang von allem anderen. Sie müssen auch festlegen, dass die Hintergrundfarbe der Seitensteuerung gelöscht wird. Die letzten beiden Zeilen könnten in Ihrem App-Delegaten erscheinen.

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

btw - Ich bemerke keine Endlosschleifen, wie oben erwähnt.

1

Sie müssen eine benutzerdefinierte UIPageControl implementieren und sie der Ansicht hinzufügen. Wie andere bereits erwähnt haben, muss view.bringSubviewToFront(pageControl) aufgerufen werden.

Ich habe eine example eines View-Controller mit dem gesamten Code auf einer benutzerdefinierten Einrichtung UIPageControl (in Storyboard) mit UIPageViewController

, die Sie Es gibt zwei Methoden benötigen die aktuelle Seite Anzeige einstellen zu implementieren.

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

Hier ist eine RxSwift/RxCocoa Antwort, die ich nach dem Betrachten der anderen Antworten zusammengestellt habe.

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 { $0.1 } 
     .map { $0.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) 
} 
Verwandte Themen