プログラムでページをめくることは可能UIPageViewController
ですか?
17 に答える
はい、次の方法で可能です:
- (void)setViewControllers:(NSArray *)viewControllers
direction:(UIPageViewControllerNavigationDirection)direction
animated:(BOOL)animated
completion:(void (^)(BOOL finished))completion;`
これは、ページの最初のビュー コントローラーを設定するために使用される方法と同じです。同様に、それを使用して他のページに移動できます。
viewControllers
単一のビュー コントローラーではなく、なぜ配列なのだろうか?
これは、ページ ビュー コントローラーが (iBooks のように) 「スパイン」を持ち、一度に 2 ページのコンテンツを表示できるためです。一度に 1 ページのコンテンツを表示する場合は、1 要素の配列を渡すだけです。
Swift での例:
pageContainer.setViewControllers([displayThisViewController], direction: .Forward, animated: true, completion: nil)
これも必要だったので、これを行う方法について詳しく説明します。
注:UIPageViewController
構造を生成するために標準のテンプレートフォームを使用したと仮定します。これには、呼び出し時にmodelViewController
とが作成されます。dataViewController
私が書いた内容がわからない場合は、戻って、をUIPageViewController
基本として使用する新しいプロジェクトを作成してください。あなたはそれから理解するでしょう。
したがって、特定のページにめくる必要がある場合は、上記のメソッドのさまざまな部分を設定する必要があります。この演習では、2つのビューが表示されている横向きのビューであると想定しています。 また、これをIBActionとして実装したので、ボタンを押すかどうかに関係なく、セレクターを呼び出して必要なアイテムを渡すのも簡単です。
したがって、この例では、表示される2つのビューコントローラーが必要です。オプションで、本を前に進めるか後ろに進めるかを指定できます。
4ページと5ページに移動し、フォワードスリップを使用する場所をハードコーディングしただけであることに注意してください。ここから、これらのアイテムを取得するのに役立つ変数を渡すだけでよいことがわかります...
-(IBAction) flipToPage:(id)sender {
// Grab the viewControllers at position 4 & 5 - note, your model is responsible for providing these.
// Technically, you could have them pre-made and passed in as an array containing the two items...
DataViewController *firstViewController = [self.modelController viewControllerAtIndex:4 storyboard:self.storyboard];
DataViewController *secondViewController = [self.modelController viewControllerAtIndex:5 storyboard:self.storyboard];
// Set up the array that holds these guys...
NSArray *viewControllers = nil;
viewControllers = [NSArray arrayWithObjects:firstViewController, secondViewController, nil];
// Now, tell the pageViewContoller to accept these guys and do the forward turn of the page.
// Again, forward is subjective - you could go backward. Animation is optional but it's
// a nice effect for your audience.
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
// Voila' - c'est fin!
}
このコードはうまくいきました、ありがとう。
これは私がそれでやったことです。前後に進むためのメソッドと、特定のページに直接移動するためのメソッド。縦向きの6ページのドキュメント用です。pageViewController テンプレートの RootController の実装に貼り付ければ問題なく動作します。
-(IBAction)pageGoto:(id)sender {
//get page to go to
NSUInteger pageToGoTo = 4;
//get current index of current page
DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];
//get the page(s) to go to
DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo - 1) storyboard:self.storyboard];
DataViewController *secondPageViewController = [self.modelController viewControllerAtIndex:(pageToGoTo) storyboard:self.storyboard];
//put it(or them if in landscape view) in an array
NSArray *theViewControllers = nil;
theViewControllers = [NSArray arrayWithObjects:targetPageViewController, secondPageViewController, nil];
//check which direction to animate page turn then turn page accordingly
if (retreivedIndex < (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
[self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}
if (retreivedIndex > (pageToGoTo - 1) && retreivedIndex != (pageToGoTo - 1)){
[self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];
}
}
-(IBAction)pageFoward:(id)sender {
//get current index of current page
DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];
//check that current page isn't first page
if (retreivedIndex < 5){
//get the page to go to
DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex + 1) storyboard:self.storyboard];
//put it(or them if in landscape view) in an array
NSArray *theViewControllers = nil;
theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];
//add page view
[self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}
}
-(IBAction)pageBack:(id)sender {
//get current index of current page
DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger retreivedIndex = [self.modelController indexOfViewController:theCurrentViewController];
//check that current page isn't first page
if (retreivedIndex > 0){
//get the page to go to
DataViewController *targetPageViewController = [self.modelController viewControllerAtIndex:(retreivedIndex - 1) storyboard:self.storyboard];
//put it(or them if in landscape view) in an array
NSArray *theViewControllers = nil;
theViewControllers = [NSArray arrayWithObjects:targetPageViewController, nil];
//add page view
[self.pageViewController setViewControllers:theViewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:NULL];
}
}
dataSource のメソッドを使用するのはどうですか?
UIViewController *controller = [pageViewController.dataSource pageViewController:self.pageViewController viewControllerAfterViewController:pageViewController.viewControllers.firstObject];
[pageViewController setViewControllers:@[controller] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
類推的に後方に。
ただし、この「self.pageViewController setViewControllers」メソッド呼び出しを使用しても、離れたページの viewController で「viewDidDissapear」は呼び出されませんが、手動でページをめくると、離れたページで viewDidDissapear が呼び出されます。これがクラッシュの原因だと思います
「提供されたビュー コントローラーの数 (0) が、要求された遷移に必要な数 (1) と一致しません」
スウィフトでは:
import UIKit
extension HomeViewController {
// MARK: - Carousel management.
func startTimerForMovingCarousel(let numberOfSecondsBetweenFiringsOfTheTimer: NSTimeInterval) {
if (self.timerForMovingCarousel == nil) {
self.timerForMovingCarousel = NSTimer.scheduledTimerWithTimeInterval(numberOfSecondsBetweenFiringsOfTheTimer,
target: self,
selector: "moveCarousel",
userInfo: nil,
repeats: true)
}
}
func moveCarousel() {
println("I move the carousel.")
let currentContentViewControllerDisplayed = self.pageViewController!.viewControllers[0] as! ContentViewController
var index: Int = currentContentViewControllerDisplayed.index
if index == self.arrayViewControllers.count - 1 {
index = 0
} else {
++index
}
let contentViewControllerToDisplay = self.arrayViewControllers[index] as! ContentViewController
self.pageViewController.setViewControllers([contentViewControllerToDisplay],
direction: UIPageViewControllerNavigationDirection.Forward,
animated: true,
completion: nil)
self.pageControl.currentPage = contentViewControllerToDisplay.index
}
func invalidateTimerForMovingCarousel() {
if (self.timerForMovingCarousel != nil) {
self.timerForMovingCarousel.invalidate()
self.timerForMovingCarousel = nil
}
}
}
また、PageViewControllerを左に移動するためのボタンも必要でした。これは、スワイプモーションから期待されることを正確に実行する必要があります。
自然なスワイプナビゲーションを処理するために「 pageViewController:viewControllerBeforeViewController 」内にすでにいくつかのルールが設定されているため、ボタンですべてのコードを再利用したいと考えていました。以前のように特定のインデックスを使用してページにアクセスする余裕はありませんでした。答えはしました。それで、私は別の解決策をとらなければなりませんでした。
次のコードは、カスタムViewController内のプロパティであり、スパインがmidに設定されているPageViewController用であることに注意してください。
[左に移動]ボタン用に作成したコードは次のとおりです。
- (IBAction)btnNavigateLeft_Click:(id)sender {
// Calling the PageViewController to obtain the current left page
UIViewController *currentLeftPage = [_pageController.viewControllers objectAtIndex:0];
// Creating future pages to be displayed
NSArray *newDisplayedPages = nil;
UIViewController *newRightPage = nil;
UIViewController *newLeftPage = nil;
// Calling the delegate to obtain previous pages
// My "pageViewController:viewControllerBeforeViewController" method returns nil if there is no such page (first page of the book).
newRightPage = [self pageViewController:_pageController viewControllerBeforeViewController:currentLeftPage];
if (newRightPage) {
newLeftPage = [self pageViewController:_pageController viewControllerBeforeViewController:newRightPage];
}
if (newLeftPage) {
newDisplayedPages = [[NSArray alloc] initWithObjects:newLeftPage, newRightPage, nil];
}
// If there are two new pages to display, show them with animation.
if (newDisplayedPages) {
[_pageController setViewControllers:newDisplayedPages direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}
}
ここから右のナビゲーションボタンを作成するのと非常によく似たことができます。
- (void)moveToPage {
NSUInteger pageIndex = ((ContentViewController *) [self.pageViewController.viewControllers objectAtIndex:0]).pageIndex;
pageIndex++;
ContentViewController *viewController = [self viewControllerAtIndex:pageIndex];
if (viewController == nil) {
return;
}
[self.pageViewController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
}
// このメソッドを呼び出します
[自己 moveToPage];
私はそれがうまくいくことを願っています:)
単一ページの場合、@Jack Humphries の回答を編集しました
-(void)viewDidLoad
{
counter = 0;
}
-(IBAction)buttonClick:(id)sender
{
counter++;
DataViewController *secondVC = [self.modelController viewControllerAtIndex:counter storyboard:self.storyboard];
NSArray *viewControllers = nil;
viewControllers = [NSArray arrayWithObjects:secondVC, nil];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
}
私は昨日からそれに取り組んでいて、ついに仕事をしました。子ビューとして3つの異なるビューコントローラーがあるため、標準テンプレートを完全に使用できませんでした:
1 - rootViewController;
2 - model;
3 - viewControllers
3.1 - VC1;
3.2 - VC2;
3.3 - VC3.
Note: all of VCs has Storyboard ID.
最初の 1 つの VC にのみトリガー ボタンが必要だったので、pageViewController とモデルのプロパティを 1 つ追加しました。
#import <UIKit/UIKit.h>
#import "Model.h"
@interface VC1 : UIViewController
@property (nonatomic, strong) UIPageViewController *thePageViewController;
@property (nonatomic, strong) SeuTimePagesModel *theModel;
@end
モデルの init メソッドを書き直して、storyboard と pageViewController をパラメーターとして渡し、VC1 に設定できるようにしました。
- (id)initWithStoryboard:(UIStoryboard *)storyboard
andPageViewController:(UIPageViewController *)controller
{
if (self = [super init])
{
VC1 *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"VC1"];
vc1.pageViewController = controller;
vc1.model = self;
VC2 *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"VC2"];
VC3 *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"VC3"];
self.pageData = [[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil];
}
return self;
}
最後に、vc1 に IBAction を追加して、pageViewController メソッドsetViewControllers:direction:animated:completion:をトリガーします。
- (IBAction)go:(id)sender
{
VC2 *vc2 = [_model.pages objectAtIndex:1];
NSArray *viewControllers = @[vc2];
[_pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}
VC インデックスを見つける必要がないことに注意してください。ボタンをクリックすると 2 番目の VC に移動しますが、すべてのインデックスを取得し、子ビューを追跡するのは難しくありません。
- (IBAction)selecionaSeuTime:(id)sender
{
NSUInteger index = [_model.pages indexOfObject:self];
index++;
VC2 *vc2 = [_model.pages objectAtIndex:1];
NSArray *viewControllers = @[vc2];
[_pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}
お役に立てば幸いです。