UIPageViewController / TextKit在分页时回流文本 [英] UIPageViewController/TextKit Reflowing Text on paging
问题描述
我正在开发一个由TextKit支持的多页面阅读应用程序,它基于WWDC 2013的高级文本布局和文本工具包效果会话(但是从不完整的示例重建了一些代码)。基本结构是您预先计算文本所需的页数,然后为每个页面创建一个NSTextContainer并将其添加到NSLayoutManager。每当UIPageViewController请求下一页或上一页时,您创建一个新的UITextView并通过从NLayoutManger的NSTextContainers数组中选择正确的一个来设置其后备文本容器。
I'm working on a multi-page reading application backed by TextKit, based off of the "Advanced Text Layouts and Effects with Text Kit" session from WWDC 2013 (but with some code reconstructed from incomplete example). The basic structure is you calculate the number of pages needed for your text upfront, then create an NSTextContainer for each page and add it to the NSLayoutManager. Whenever the UIPageViewController asks for the next or previous page, you create a new UITextView and set its backing text container by selecting the correct one out of the NLayoutManger's array of NSTextContainers.
不幸的是,我遇到了一个问题,即文本在第一页和第一次回页到任何给定页面时都被重排。这是它的样子:
Unfortunately, I have a problem where the text gets reflowed both on the first page, and the first time that I page back to any given page. Here's what it look like:
这不是最明显的效果(如果你错过了,在回传时注意屏幕的顶部),但它有点迷惑,我我想尽可能消除它。鉴于文本容器应该预先计算,我不明白它为什么要回流文本,或者如何防止它。有谁知道问题是什么?
It's not the most glaring effect (if you missed it, pay attention to the top of the screen when paging back), but it is a little disorienting, and I'd like to eliminate it if possible. Given that the text containers should be calculated up front, I don't understand why it's reflowing the text, or how to prevent it. Does anyone know what the problem is?
编辑:添加代码示例。
@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 = [[NSLayoutManager alloc] init];
[self.layoutManager setTextStorage:self.currentDocument];
self.layoutManager.delegate = self;
_pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
self.pageViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.pageViewController.dataSource = self;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
// the numberOfPages accessor lazily calculates the number of pages needed to contain the document
for (int i = 0; i < self.numberOfPages; ++i) {
NSTextContainer *container = [[NSTextContainer alloc] init];
container.size = [self _textFrame].size;
[self.layoutManager addTextContainer:container];
}
[self.pageViewController setViewControllers:@[[self viewControllerForPageNumber:0]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
}
- (UIViewController *)viewControllerForPageNumber:(NSUInteger)pageNumber {
if (pageNumber >= self.numberOfPages) {
return nil;
}
// SinglePageViewController is a lightweight view controller that has a UITextView and a page number
SinglePageViewController *vc = [[SinglePageViewController alloc] init];
UITextView *textView = [[UITextView alloc] initWithFrame:[self _textFrame] textContainer:[self.layoutManager.textContainers objectAtIndex:pageNumber]];
textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
textView.scrollEnabled = NO;
textView.editable = NO;
[textView setFont:[UIFont fontWithName:@"IowanOldStyle-Roman" size:20.f]];
[vc.view addSubview:textView];
vc.textView = textView;
vc.pageNumber = pageNumber;
return vc;
}
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger currentPage = [(SinglePageViewController *)viewController pageNumber];
if (currentPage >= self.numberOfPages) {
return nil;
}
return [self viewControllerForPageNumber:currentPage + 1];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger currentPage = [(SinglePageViewController *)viewController pageNumber];
if (currentPage == 0) {
return nil;
}
return [self viewControllerForPageNumber:currentPage - 1];
}
#pragma mark - Private
- (CGRect)_textFrame {
return CGRectInset(self.view.bounds, 5., 0.);
}
@end
推荐答案
我遇到了同样的问题。我的解决方案是在 addSubview
之后放置 scrollEnabled
将强制 textContainer
重新计算尺寸。见下面的代码:
I faced the same issue. My solution is to put the scrollEnabled
after addSubview
will force the textContainer
re-calculate the size. See below code:
vc.view.addSubview(textView)
textView.scrollEnabled = false;
更新。最后,我想我找到了正确答案......我们需要在 didChangeGeometryFromSize
回调中重置容器大小。如果不是这样,请纠正我:)
Update. Finally, I think I found the right answer... We need to reset the container size in the didChangeGeometryFromSize
callback. Please correct me if it is not true :)
func layoutManager(layoutManager: NSLayoutManager,
textContainer: NSTextContainer,
didChangeGeometryFromSize oldSize: CGSize) {
textContainer.size = self.textFrame().size;
println(textContainer.size.width)
println(textContainer.size.height)
}
这篇关于UIPageViewController / TextKit在分页时回流文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!