gpt4 book ai didi

ios - UIPageViewController 和 Storyboard

转载 作者:IT王子 更新时间:2023-10-29 07:38:57 25 4
gpt4 key购买 nike

我正在尝试从 Storyboard中专门配置一个 UIPageViewController:

enter image description here

TutorialPageViewController.h

#import <UIKit/UIKit.h>
@interface TutorialPageViewController : UIPageViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource>
@end

TutorialPageViewController.m

#import "TutorialPageViewController.h"

@interface TutorialPageViewController ()
@property (assign, nonatomic) NSInteger index;
@end

@implementation TutorialPageViewController
{
NSArray *myViewControllers;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.delegate = self;
self.dataSource = self;
[self didMoveToParentViewController:self];
UIStoryboard *tutorialStoryboard = [UIStoryboard storyboardWithName:@"TutorialStoryboard" bundle:[NSBundle mainBundle]];
UIViewController *tuto1 = [tutorialStoryboard instantiateViewControllerWithIdentifier:@"TutorialPageViewController_1"];
UIViewController *tuto2 = [tutorialStoryboard instantiateViewControllerWithIdentifier:@"TutorialPageViewController_2"];

myViewControllers = @[tuto1, tuto2, tuto1, tuto2];
self.index = 0;

[self setViewControllers:@[tuto1] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}

- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
return myViewControllers[index];
}

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

NSUInteger index = self.index;

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

// Decrease the index by 1 to return
index--;
return [self viewControllerAtIndex:index];
}

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

NSUInteger index = self.index;
index++;
if (index > [myViewControllers count]) { return nil; }

return [self viewControllerAtIndex:index];
}

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

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

@end

问题是...

  • 第一页使用页面指示器显示良好。滑动时,
  • 我能正常看到第二页。
  • 转换完成后,我立即看到黑屏(页面指示器正确显示第 2 页)。没有用户互动不再可用。

最佳答案

2020。 Swift 已更新。

2017年答案...

如今,只需使用 Storyboard 即可轻松做到这一点。

这些“滑动全屏教程”作为应用程序“介绍”流行了一段时间,所以我将下面的类称为IntroPages

第 1 步,创建一个 容器 View ,它是一个 UIPageViewController。

如果是 iOS 新手,这里有一个 container view tutorial

( 注意:如果您不知道如何将容器 View “更改”为 UIPageViewController,请向下滚动到该教程中的“如何更改...”部分!

enter image description here )

您可以将容器制成您想要的任何形状。与任何容器 View 一样,它可以是全屏或屏幕的一小部分 - 任何你想要的。

第 2 步,

制作四个简单、普通的 View Controller ,它们可以是您想要的任何东西 - 图像、文本、表格,任何东西。 (示例中为紫色。)

four controllers

请注意,它们只是放在你的 Storyboard上,不要将它们链接到任何东西。

第三步,你必须设置这四个页面的ID。 “id1”、“id2”、“id3”、“id4”都可以。

set the IDs

第四步,复制粘贴!这是 IntroPages 类,

import UIKit
class IntroPages: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

var pages = [UIViewController]()

override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.dataSource = self

let p1: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id1")
let p2: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id2")
let p3: UIViewController! = storyboard?.instantiateViewController(withIdentifier: "id3")

// etc ...

pages.append(p1)
pages.append(p2)
pages.append(p3)

// etc ...

setViewControllers([p1], direction: UIPageViewController.NavigationDirection.forward, animated: false, completion: nil)
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController)-> UIViewController? {

let cur = pages.firstIndex(of: viewController)!

// if you prefer to NOT scroll circularly, simply add here:
// if cur == 0 { return nil }

var prev = (cur - 1) % pages.count
if prev < 0 {
prev = pages.count - 1
}
return pages[prev]
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController)-> UIViewController? {

let cur = pages.firstIndex(of: viewController)!

// if you prefer to NOT scroll circularly, simply add here:
// if cur == (pages.count - 1) { return nil }

let nxt = abs((cur + 1) % pages.count)
return pages[nxt]
}

func presentationIndex(for pageViewController: UIPageViewController)-> Int {
return pages.count
}
}

(查看评论 - 根据您的喜好,有用于循环线性分页的代码。)

在 Storyboard 上查看 UIPageViewController。将类设置为 IntroPages

这就是它的全部 - 你已经完成了。

您只需在 Storyboard上设置过渡样式,

enter image description here

您很可能想要“Scroll”,而不是另一个。

大功告成!而现在……


添加UIPageControl的介绍...

您将 UIPageControl 添加到最高级别的包装类中,如上图示例中的“Intro”。

(所以,令人惊讶的是在页面 View Controller 中,不在“IntroPages”中。)

因此,在 Storyboard上,非常简单地将 UIPageControl 拖到“Intro”上。

注意!奇怪的是,在 Storyboard中,您无法移动 UIPageControl

当您将页面控件拖到 View Controller 上时,它只是位于一个固定的位置。这完全是奇怪的,但事实就是如此。不要浪费时间尝试移动它:)

在 Intro 中,您需要以通常的方式访问页面 View Controller (IntroPages):

class Intro: UIViewController {

@IBOutlet var pageControl: UIPageControl!
var pageViewController: IntroPages!

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueIntroPages" {
// if new to container views, identifier explained here:
// https://stackoverflow.com/a/23403979/294884
pageViewController = (segue.destination as! IntroPages)
}
}

override func viewDidLoad() {
super.viewDidLoad()
view.bringSubviewToFront(pageControl)
pageControl.currentPage = 0
}

注意这个关键行:

    view.bringSubviewToFront(pageControl)

添加这个函数

@IBAction func userDidChangePageControl(_ sender: UIPageControl) {}

然后在 Storyboard 中单击页面控件并将 valueChanged 拖到该函数。

函数的最简单的大纲版本

@IBAction func userDidChangePageControl(_ sender: UIPageControl) {
pageViewController.setViewControllers(
[pageViewController.pages[newIndex]],
direction: (pageViewController.currentIndex < newIndex)
? .forward : .reverse,
animated: true, completion: nil)
}

但是请参阅此 QA https://stackoverflow.com/questions/66545624 以获得更全面的调查。

在 IntroPages 中添加属性...

var currentIndex: Int {
if let visibleViewController = viewControllers?.first,
let ci = pages.firstIndex(of: visibleViewController) {
return ci
}
else {
return 0
}
}

在 IntroPages 中还添加以下内容,这样,当用户滑动屏幕时,UIPageControl 知道该做什么:

func pageViewController(_ pageViewController: UIPageViewController, 
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
(parent as? Intro)?.pageControl.currentPage = currentIndex
}

由于 Apple 错误/异常行为,在 IntroPages 中还添加了以下内容:

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let subViews = view.subviews
var scrollView: UIScrollView? = nil
var pageControl: UIPageControl? = nil

// maintain this code order...
for view in subViews {
if view.isKind(of: UIScrollView.self) {
scrollView = view as? UIScrollView
}
else if view.isKind(of: UIPageControl.self) {
pageControl = view as? UIPageControl
}
}

// maintain this code order...
if (scrollView != nil && pageControl != nil) {
scrollView?.frame = view.bounds
if let pageControl = pageControl {
view.bringSubviewToFront(pageControl) }
}
}

你在路上。

关于ios - UIPageViewController 和 Storyboard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18398796/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com