UIPageViewController / TextKit在分页时回流文本 [英] UIPageViewController/TextKit Reflowing Text on paging

查看:96
本文介绍了UIPageViewController / TextKit在分页时回流文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个由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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆