UIPageViewController/TextKit 在分页上回流文本

2024-01-26

我正在开发一个由 TextKit 支持的多页阅读应用程序,该应用程序基于 WWDC 2013 的“Advanced Text Layouts and Effects with Text Kit”会议(但有些代码是根据不完整的示例重建的)。基本结构是预先计算文本所需的页面数,然后为每个页面创建一个 NSTextContainer 并将其添加到 NSLayoutManager 中。每当 UIPageViewController 请求下一页或上一页时,您都会创建一个新的 UITextView 并通过从 NLayoutManger 的 NSTextContainers 数组中选择正确的一个来设置其后台文本容器。

不幸的是,我遇到了一个问题,即文本在第一页上以及第一次翻回任何给定页面时都会重新排列。它看起来是这样的:

这不是最明显的效果(如果你错过了,请在回页时注意屏幕顶部),但它有点让人迷失方向,如果可能的话我想消除它。鉴于文本容器应该预先计算,我不明白为什么它要回流文本,或者如何防止它。有谁知道问题是什么?

EDIT:添加代码示例。

@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

我遇到了同样的问题。我的解决方案是把scrollEnabled after addSubview将迫使textContainer重新计算尺寸。见下面的代码:

vc.view.addSubview(textView)
textView.scrollEnabled = false;

Update。最后,我想我找到了正确的答案......我们需要重置容器大小didChangeGeometryFromSize打回来。如果不正确请纠正:)

func layoutManager(layoutManager: NSLayoutManager, 
                   textContainer: NSTextContainer, 
                   didChangeGeometryFromSize oldSize: CGSize) {

    textContainer.size = self.textFrame().size;
    println(textContainer.size.width)
    println(textContainer.size.height)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UIPageViewController/TextKit 在分页上回流文本 的相关文章

随机推荐

  • 使用 Namecheap DNS 的 Amazon S3 静态托管 - 如何正确路由非 www 前缀 URL

    我一直在阅读其他帖子 试图深入了解这个问题 但我需要一些澄清 当我进入时 我能够让所有域请求完美地到达我的 Amazon S3 存储桶www example com MyDirectory 如果我输入example com MyDirect
  • 使用 Glide 加载到 Imageview 但延迟

    我使用 Glide 从 Firebase 加载 ImageView 当我运行我的应用程序时 我的 ImageView 会延迟 就像我视频中的牙齿一样 https www youtube com watch v 6Mj0Xq3M8n0 htt
  • DB Design允许用户定义产品、产品规格并让自己插入订单

    我正在设计一个数据库 因为我需要开发这样一个 CRM 用户可以在其中指定新产品 产品规格和定价 然后让自己为上一步中指定的产品插入订单 当然 插入的数据需要根据它们在数据库中指定的内容进行评估 我举个例子可能会更清楚 user1 创建一个产
  • 我的项目不支持多设备屏幕视图

    我有一个菜单屏幕 XML 当我打开项目宽屏幕时 它不适应所有屏幕尺寸 我怎样才能克服这个问题 当我想添加有关此问题的图片时 我认为我需要 10 次代表 观点 有人可以帮助我吗
  • 寻找 C++ 的应用程序 GUI 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在考虑编写一个非常简单的绘画程序 我想要一种更高级的方法来将数据输入到我的程序中 例如颜色 画笔的
  • 命名空间“卡住”为终止,我如何删除它

    我有一个 卡住 的命名空间 我删除了它 显示在这个永恒的 终止 状态中 假设您已经尝试强制删除资源 例如 Pod 停留在终止状态 https stackoverflow com q 35453792 而你却束手无策地试图恢复名称空间 您可以
  • 命令行从 TFS“获取最新”,无需映射工作区等

    我假设 tf exe get project recursive 需要这个奇怪的工作区映射 已知的 TFS 服务器等 有什么办法可以做这个最简单的事情 连接到thisTFS 服务器使用this一组凭据 获取最新的源代码this项目并把它he
  • 如何从程序窗口外部获取鼠标事件

    我想拖动这个角色 图像 所以我使用这个方法来获取鼠标位置 WndProc HWND hWnd UINT message WPARAM wParam LPARAM lParam switch message case WM LBUTTONDO
  • 具有白色轮廓的 OpenGL 彩色位图字体

    我有一个 libgdx 游戏 我想在其中使用带有轮廓的位图字体 我希望能够使用 setColor 设置字体颜色 但是 我总是希望轮廓保持白色 对我来说实现这一目标的最佳方法是什么 我假设我应该使用片段着色器进行所需的颜色操作 我创建了一个位
  • 在finally块中抛出异常

    有没有一种优雅的方式来处理抛出的异常finally block 例如 try Use the resource catch Exception ex Problem with the resource finally try resourc
  • 找不到方法 android java.lang.NoClassDefFoundError 引用的类

    我正在调用一个单独的类 我已经在与我的包相同的包中编写了MainActivity类已保存 但是当我运行该应用程序时它给了我java lang NoClassDefFoundError 我不明白为什么无法识别同一包中定义的另一个类 我尝试过很
  • 在使用关联类型的情况下,如何为通用容器实现 Borrow?

    我想实施Borrow for UserFriendlyDataStructure提供对internal data函数内的字段应该与数据提供者无关 的类型internal data字段由与特征相关的类型决定TraitA 请注意 Sealed特
  • X500主要杰出姓名顺序

    我使用 Bouncycastle 库通过 X509v3CertificateBuilder 类从 PKCS10 请求生成证书 它返回构建一个包含生成的证书的 X509CertificateHolder 对象 如果我在持有者上调用 getIs
  • SoundCloud 自动在其移动网站上播放下一首歌曲如何?

    好的 我知道 iOS 不允许自动播放 但是 SoundCloud 如何在其移动网站上自动播放下一首歌曲呢 我可以获得我想要填充 iframe src 的下一首歌曲 并且小部件会重新加载以显示该曲目 我尝试了很多解决方法 即使我在下一首曲目准
  • Python 脚本的桌面启动器以错误的路径启动程序

    我无法从 Linux Mint 17 1 Cinnamon 上创建的 desktop 启动器启动 python 脚本 问题是脚本将在错误的路径中启动 即主文件夹而不是它所在的目录 因此 它无法在其文件夹中找到伴随它的其他重要文件 因此无法工
  • 检查列表是否由 X 的 N 个实例组成(重复 X N 次)

    给定一个查询 例如 containsN 4 2 Z 我应该得到 Z 2 2 2 2 or containsN 4 W 3 3 3 3 我应该得到 W 3 换句话说 对于第一个示例 我需要绑定到 Z 的列表中 2 的 4 个实例 对于第二个示
  • 使用 Python 从法语 Word 文档中提取 XML 时出现问题:生成非法字符

    在过去的几天里 我一直在尝试创建一个脚本 该脚本将 1 从 Word 文档中提取 XML 2 修改该 XML 3 使用新的 XML 创建并保存新的 Word 文档 在许多 stackoverflow 用户的帮助下 我最终找到了看起来非常有前
  • 如何在 iPadOS15 safari 中禁用放大镜

    我想禁用当我们长按任何 html 元素时出现的文本放大镜 它开始再次出现在 iOS 15 中 我尝试了以下方法 但在 iOS 15 上不起作用 在 iOS html 应用程序中禁用放大镜 https stackoverflow com qu
  • OSGi 配置管理服务的现有实现?

    我们正在考虑使用配置管理服务作为主要 API 用于配置基于 OSGi 的应用程序中的组件 如果我们可以重用一些现有的实现 那就太好了 所以我正在尝试调查和评估最受欢迎的实现 我知道有 Apache Felix 配置管理 http felix
  • UIPageViewController/TextKit 在分页上回流文本

    我正在开发一个由 TextKit 支持的多页阅读应用程序 该应用程序基于 WWDC 2013 的 Advanced Text Layouts and Effects with Text Kit 会议 但有些代码是根据不完整的示例重建的 基本