我正在使用 UIPageViewContoller 来创建类似书籍的翻页体验。我的书的页面比 iPhone 屏幕的全宽窄 18 像素,并固定在屏幕的左侧。然后,我的 UIPageViewController 视图的框架设置为这些页面的框架大小(宽度:302,高度:460)。我这样做是为了产生书有多个页面的效果,并且翻页看起来像是从当前可见页面的边缘开始,就像 iBooks 应用程序中的体验一样。
我遇到的问题是,如果有人尝试通过从屏幕最右侧平移超过 302 px 点来翻页,则 UIPageViewController 不会捕获平移手势,并且不会翻页。我看到很多用户尝试以这种方式翻页,所以我想在不改变 UI 设计的情况下修复这种体验。
我的想法是,我可以从 UIPageViewController 外部的区域获取 UIPanGesture 并将其传递给 UIPageViewController。我已经使用作为整个视图背景的图像视图成功捕获了平移手势,但我不知道如何将手势传递给 UIPageViewController 来处理翻页。
- (void) viewDidLoad {
...
// Add a swipe gesture recognizer to grab page flip swipes that start from the far right of the screen, past the edge of the book page
self.panGesture = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:nil] autorelease];
[self.panGesture setDelegate:self];
[self.iv_background addGestureRecognizer:self.panGesture];
//enable gesture events on the background image
[self.iv_background setUserInteractionEnabled:YES];
... …Run Code Online (Sandbox Code Playgroud) iphone uigesturerecognizer uipangesturerecognizer uipageviewcontroller
如果viewControllerBeforeViewController viewControllerAfterViewController任一方法返回 nil,则也会调用计数器部分。
这种行为是预期行为吗?无论如何我都可以阻止这件事发生。这就是我试图做的事情。
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if ([viewController isKindOfClass:[QuestionViewController class]]){
QuestionViewController* qvc = (QuestionViewController*)viewController;
CVPQuestion* prevQuestion = [_surveyContext previousQuestion:qvc.question];
return [self questionControllerWithQuestion:prevQuestion];
}
if ([viewController isKindOfClass:[SurveyEndedViewController class]]){
return [self questionControllerWithQuestion:[self.questionList lastObject]];
}
return nil;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(QuestionViewController *)viewController {
if ([viewController respondsToSelector:@selector(question)]){
CVPQuestion* nextQuestion = [_surveyContext previousQuestion:viewController.question];
if (nextQuestion == nil && ![_surveyContext isAnswered:viewController.question]){
[viewController showToasterWithText:@"Please answer the question to continue"];
}
QuestionViewController* qc = [self questionControllerWithQuestion:[_surveyContext nextQuestion:viewController.question]];
if (!qc){return …Run Code Online (Sandbox Code Playgroud) 我正在开发一个由 TextKit 支持的多页阅读应用程序,该应用程序基于 WWDC 2013 的“Advanced Text Layouts and Effects with Text Kit”会议(但有些代码是根据不完整的示例重建的)。基本结构是预先计算文本所需的页面数,然后为每个页面创建一个 NSTextContainer 并将其添加到 NSLayoutManager 中。每当 UIPageViewController 请求下一页或上一页时,您都会创建一个新的 UITextView 并通过从 NLayoutManger 的 NSTextContainers 数组中选择正确的一个来设置其背景文本容器。
不幸的是,我遇到了一个问题,即文本在第一页上以及第一次翻回任何给定页面时都会重新排列。它看起来是这样的:

这不是最明显的效果(如果你错过了,请在回页时注意屏幕顶部),但它有点让人迷失方向,如果可能的话我想消除它。鉴于文本容器应该预先计算,我不明白为什么它要回流文本,或者如何防止它。有谁知道问题是什么?
编辑:添加代码示例。
@interface ReaderViewController () <UIPageViewControllerDataSource>
@property (nonatomic, assign) NSUInteger numberOfPages;
@property (nonatomic, retain) UIPageViewController *pageViewController;
@property (nonatomic, retain) NSTextStorage *currentDocument;
@property (nonatomic, retain) NSLayoutManager *layoutManager;
@end
@implementation ReaderViewController
- (instancetype)initWithDocument:(NSTextStorage *)document {
if ((self = [super init])) {
_currentDocument = document;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_layoutManager = …Run Code Online (Sandbox Code Playgroud) 我UIPageViewController以编程方式创建一个并将其作为子项添加到我的容器视图控制器中,如下所示:
override func viewDidLoad() {
super.viewDidLoad()
self.pageViewController = UIPageViewController(transitionStyle:.PageCurl, navigationOrientation:.Horizontal, options: nil)
self.mainImageView!.userInteractionEnabled = true
self.pageViewController.delegate = self
self.pageViewController.dataSource = self.modelController
self.addChildViewController(self.pageViewController)
self.view.addSubview(self.pageViewController.view)
self.pageViewController.didMoveToParentViewController(self)
}
Run Code Online (Sandbox Code Playgroud)
问题在于视图的UIPageViewController大小不正确,如下面的视图层次结构所示。的数据源返回的视图控制器包含UIPageViewController单个UIScrollView. 我已经设置了约束,UIScrollView以便滚动视图扩展到超级视图。
在我看来,问题源于这样一个事实:scrollView 约束与容器视图的约束“分离”,但我不知道如何使用 StoryBoard 修复它,因为这些是不同视图控制器中的视图。我不太熟悉以编程方式指定约束,并且迄今为止我以编程方式设置约束的努力都失败了。
如何解决此问题,以便视图控制器的滚动视图UIPageViewController正确包含在容器 ViewController 的视图内?


好吧,我在整个网络上搜索了我的具体问题的解决方案,但无法弄清楚。
我正在开发一个针对 iOS 8.1 的 swift 阅读器应用程序,我的DetailViewController(应该显示文章的控制器)具有以下设置:
-UIView
--UIScrollView
---UIView (contentView)
----UIScrollView(horizontal only)
----TextView
----SegmentedControl
----ContainerView (wired up with a UIPageViewController)
Run Code Online (Sandbox Code Playgroud)
PageViewController 当前有 2 个控制器作为子视图,以便显示文章或评论(两者:文章内容的动态高度标签/评论的 tableviewcells)。在使用 UIPageViewController 之前,我使用 UIView 作为自定义容器(内容视图的直接子视图)和表视图(也是内容视图的直接子视图),如果选择了某个段索引,则将其切换为隐藏/显示。现在我想使用一种更好的方法,可以在两个“选项卡”之间滑动。因此,我在单独的控制器中设计了由 pageviewcontroller 管理的子视图。
问题:我的 UIScrollView 没有全高显示文章/评论。UIScrollView 布置其子视图,随后 pageviewcontroller 中包含的视图控制器正在获取数据并填充文本视图以显示它。我尝试采用 Apple此处描述的纯自动布局方法。因此,我设置了从内容视图到滚动视图以及从滚动视图到其超级视图的所有必要约束。由于 Scrollview 无法正确计算其内容大小(它所知道的只是有几个子视图和一个容器视图),我还为内容视图添加了一个高度约束,我试图在运行时替换它。所以我尝试了一些上面列出的方法,如下所示:
iOS:制作具有动态高度的 UIScrollView 的最佳方法?
以及其他教程,例如:
http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
但无法让它发挥作用。要么不显示任何内容(如果仅存在占位符高度约束),要么不滚动,因为高度由约束固定。例如,如果我在运行时将 contentView 的高度限制设置为 1000,它可以工作,但当然它不是动态的,因此这不是我想要的。我希望 ScrollView 在更改“选项卡”时随着其子视图的增长/收缩而缩放。
如果需要,我可以提供代码或构建一个示例项目来展示问题。到目前为止,我在 AutoLayout 或 UIScrollView 方面从未遇到过任何问题,但这次我不知道如何完成任务。
我希望我清楚地说明了一切并且有人可以提供帮助。谢谢!
有没有办法确定 UIPageViewController 在左/右滑动时的平移位置?我一直在努力实现这一目标,但它不起作用。我添加了一个 UIPageViewController 作为子视图,我可以水平向左/右滑动它以在页面之间切换,但是我需要确定我在屏幕上平移的位置的 x,y 坐标。
我使用UIPageViewController卷曲效果来启用水平滑动黑白视图控制器。但是内容大小大于视图的高度。所以我UIScrollView在视图控制器中添加了支持垂直滚动。我在视图控制器中添加了此代码来设置内容滚动视图的大小-
-(void)viewDidLayoutSubviews
{
[self.scrollView setContentSize:CGSizeMake(100, 900)];
}
Run Code Online (Sandbox Code Playgroud)
问题是,当视图控制器加载到UIPageViewController滚动视图中时,当我尝试滚动它时,它最初不会滚动,但一旦我加载下一个控制器(通过水平滑动)它就会滚动并返回到第一个视图控制器。我做错了什么?任何帮助或建议将不胜感激。
我有一个包含 3 页的页面视图控制器。我希望在所有这些按钮之上都可以看到一个“浮动”按钮。我曾尝试为 PageView 使用容器视图,但这似乎不起作用。我还能如何让按钮在所有 3 个页面中保持可见?
我已尝试使用此问题中所述的容器视图: UIButton 跨 UIPageViewController 的所有页面
我通过线程在 SwiftUI 中成功实现了 PageView:
如何在 SwiftUI 中实现 PageView?
只要所有视图都具有相同的结构,通过数组传递多个视图就像一个魅力。
PageView([TestView(), TestView()]).
但是,我想传递不同的观点。
PageView([TestView(), AnotherView(), DifferentView()]).
所有视图都是 SwiftUI 类型:
struct NAME : View { code }
当我尝试向数组添加不同的结构时,我收到以下错误消息:
var pageViewViewArray = [TestView(), AnotherView(), DifferentView()]
Run Code Online (Sandbox Code Playgroud)
异构集合字面量只能推断为“[Any]”;如果这是有意的,请添加显式类型注释。
插入'为[任何]
通过将其转换为:
var pageViewViewArray = [TestView(), AnotherView(), DifferentView()] as! [Any]
PageView(pageViewViewArray)
Run Code Online (Sandbox Code Playgroud)
PageView 会说:
协议类型“Any”不能符合“View”,因为只有具体类型才能符合协议
我将不胜感激任何想法。
在我的 SwiftUI 应用程序中,我目前有一个使用 UIKit 实现的 PageViewController。它遵循 Apple 的 SwiftUI UIKit 集成教程中概述的传统 SwiftUI - UIKit 实现。
我有填充 UIViewController 的数据,在传递给 PageViewController 的控制器数组中,由@Environment变量提供。在应用程序的不同屏幕中,您可以发出一个导致 Environment 对象更新的操作,触发位于 PageViewController 中的 ViewController 的重新渲染。
然而,这种重新渲染会导致问题,因为 ViewController 是用新标识符重新制作的,因此parent.controller在类协调器 pageViewController 函数内的数组中找不到 viewController 的索引。这会导致索引默认为 nil 并禁用更新的 viewController 上的任何滑动。我仍然可以使用页面控制点在 viewController 之间导航,但我想确定如何更新 parent.controller 数组以包含新的 ViewController 并丢弃旧的。
经过数小时的搜索、调试和修补,我一直无法找到一种方法来重置父控制器数组,用新的 ViewController 替换已丢弃的旧视图。下面是 PageViewController 的代码。
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> …Run Code Online (Sandbox Code Playgroud) ios ×7
swift ×3
autolayout ×2
swiftui ×2
uiscrollview ×2
button ×1
iphone ×1
objective-c ×1
textkit ×1
uibutton ×1
uiview ×1