web-dev-qa-db-ja.com

UIPageViewController内のスライドページの上部にUIPageControl要素を配置する方法は?

これに関して IPageViewControllerでアプリを実装する方法に関するAppCodaのチュートリアル ページの下部ではなく上部にカスタムページコントロール要素を使用したいと思います。

表示される単一のビューの上にページコントロール要素を配置するだけで、論理的な結果は、コントロール要素がページビューと共に画面から離れてスクロールすることです。

ユーザーが固定されたコントロール要素の下にビューを表示できるように、ページビューがフルスクリーン(画像のように)になるように、コントロール要素をビューの上に配置する方法はありますか?

サンプルのスクリーンショットを添付しました- AppCoda and Path

enter image description here

59
sn3ek

さらに調査し、検索した後 解決策が見つかりました 、stackoverflowでも。

キーは、カスタムUIPageControl要素に送信する次のメッセージです。

[self.view bringSubviewToFront:self.pageControl];

AppCodaチュートリアルはこのソリューションの基礎です

UIPageControlの上にRootViewController要素を追加します-矢印付きのView Controller。

ViewController.mに関連するIBOutlet要素を作成します。

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];
}
51
sn3ek

これの元となった答えについてコメントする担当者がいませんでしたが、本当に気に入っています。コードを改善し、以下のUIPageViewControllerのサブクラスのSwiftに変換しました。

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

きれいで、それはうまくいきます。何も維持する必要はなく、Page View Controllerをストーリーボードのこのクラスのインスタンスにするか、カスタムPage View Controllerクラスをこのクラスから継承します。

52
Eric F.

sn3ekあなたの答えは、私をそこに連れて行ってくれました。しかし、viewControllerCreationメソッドを使用して現在のページを設定しませんでした。

ViewController alsoUIPageViewControllerのデリゲート。次に、そのメソッドでPageControlCurrentPageを設定します。 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>
27
Coderdad

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などを維持する必要はありません。

3
zeroimpl

他の返信を見てからまとめた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 { $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)
}
2
jacks205

カスタムUIPageControlを実装し、ビューに追加する必要があります。他の人が述べたように、view.bringSubviewToFront(pageControl)を呼び出さなければなりません。

カスタムUIPageControl(ストーリーボード内)をUIPageViewControllerでセットアップするためのすべてのコードを備えたView Controllerの があります

現在のページインジケーターを設定するには、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
        }
    }
}
1
samwize

上記の@zerotoolの回答に基づいたSwifty 2の回答は次のとおりです。 UIPageViewControllerをサブクラス化してから、このオーバーライドを追加してscrollviewを見つけ、サイズを変更します。次に、ページコントロールを取得し、それを他のすべての最上部に移動します。また、ページコントロールの背景色をクリアに設定する必要があります。最後の2行は、アプリのデリゲートに含めることができます。

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-上記のように、無限ループに気付いていません。

0
Lee Probert