简体   繁体   English

在iPad上呈现长文档

[英]Rendering a Long Document on iPad

I'm implementing a document viewer with highlighting/annotation capabilities for a custom document format on iPad. 我正在为iPad上的自定义文档格式实现具有突出显示/注释功能的文档查看器。 The documents are kind of long (100 to 200 pages, if printed on paper) and I've had a hard time finding the right approach. 这些文件有点长(100到200页,如果在纸上打印),我很难找到正确的方法。 Here are the requirments: 以下是要求:

1) Basic rich-text styling: control of left/right margins. 1)基本的富文本样式:控制左/右边距。 Control of font name, size, foreground/background color, and line spacing. 控制字体名称,大小,前景/背景颜色和行间距。 Bold, italics, underline, etc. 大胆,斜体,下划线等

2) Selection and highlighting of arbitrary text regions (not limited to paragraph boundaries, like in Safari/UIWebView). 2)选择和突出显示任意文本区域(不限于段落边界,如Safari / UIWebView)。

3) Customization of the Cut/Copy/Paste popup (UIMenuController) This is one of the essential requirements of the app. 3)自定义剪切/复制/粘贴弹出窗口(UIMenuController)这是应用程序的基本要求之一。

My first implementation was based on UIWebView. 我的第一个实现是基于UIWebView。 I just rendered the document as HTML with CSS for text styling. 我只是将文档渲染为带有CSS的HTML文本样式。 But I couldn't get the kind of text selection behavior I wanted (across paragraph boundaries) and the UIMenuController can't be customized from within UIWebView. 但我无法获得我想要的那种文本选择行为(跨越段落边界),并且无法从UIWebView中自定义UIMenuController。

So I started working on a javascript approach, faking the device text-selection behavior using JQuery to trap touch events and dynamically modifying the DOM to change the background color of selected regions of text. 所以我开始研究javascript方法,使用JQuery伪装设备文本选择行为来捕获触摸事件并动态修改DOM以更改所选文本区域的背景颜色。 I built a fake UIMenuController control as a hidden DIV, positioning it and unhiding it whenever there was an active selection region. 我构建了一个假的UIMenuController控件作为隐藏的DIV,定位它并在有活动选择区域时取消隐藏它。

Not too shabby. 不是太寒酸。

The main problem is that it's SLOOOOOOOW. 主要问题是它是SLOOOOOOOW。 Scrolling through the document is nice and quick, but dynamically changing the DOM is not very snappy. 滚动浏览文档非常快捷,但动态更改DOM并不是很顺畅。 Plus, I couldn't figure out how to recreate the magnifier loupe, so my fake text-selection GUI doesn't look quite the same as the native implementation. 另外,我无法弄清楚如何重新创建放大镜放大镜,因此我的假文本选择GUI与本机实现看起来并不完全相同。 Also, I haven't yet implemented the communication bridge between the javascript layer and the objective-c layer (where the rest of the app lives), but it was shaping up to be a huge hassle. 此外,我还没有实现javascript层和objective-c层之间的通信桥梁(应用程序的其余部分存在),但它正在形成一个巨大的麻烦。

So I've been looking at CoreText, but there are precious few examples on the web. 所以我一直在关注CoreText,但网上有很少的例子。 I spent a little time with this simple little demo: 我用这个简单的小演示花了一点时间:

http://github.com/jonasschnelli/I7CoreTextExample/ http://github.com/jonasschnelli/I7CoreTextExample/

It shows how to use CoreText to draw an NSAttributedText string into a UIView. 它展示了如何使用CoreText将NSAttributedText字符串绘制到UIView中。 But it has its own problems: It doesn't implement text-selection behavior, and it doesn't present a UIMenuController, so I don't have any idea how to make that happen. 但它有自己的问题:它没有实现文本选择行为,并且它没有呈现UIMenuController,所以我不知道如何实现这一点。 And, more importantly, it tries to draw the entire document all at once, with significant performance degradations for long documents. 而且,更重要的是,它试图一次性绘制整个文档,对于长文档而言会显着降低性能。 My documents can have thousands of paragraphs, and less than 1% of the document is ever on screen at a time. 我的文档可以包含数千个段落,并且一次只能在屏幕上显示不到1%的文档。

On the plus side, these documents already contain precise formatting information. 从好的方面来说,这些文档已包含精确的格式信息。 I know the exact page-position of every line of text, so I don't need a layout engine. 我知道每行文本的确切页面位置,所以我不需要布局引擎。

Does anyone know how to implement this sort of view using CoreText? 有谁知道如何使用CoreText实现这种视图? I understand that a full-fledged implementation is overkill for a question like this, but I'm looking for a good CoreText example with a few basic requirements: 我理解一个完整的实现对于这样的问题来说是过度的,但我正在寻找一个有一些基本要求的好的CoreText示例:

1) Precise layout & formatting control (using the formatting metrics and text styles I've already calculated). 1)精确的布局和格式控制(使用我已经计算过的格式化指标和文本样式)。

2) Arbitrary selection of text. 2)任意选择文本。

3) Customization of the UIMenuController. 3)UIMenuController的定制。

4) Efficient recycling of resources for off-screen objects. 4)为屏幕外对象有效地回收资源。

I'd be happy to implement my own recycling when text elements scroll off-screen, but wouldn't that require re-implementing UIScrollView? 当文本元素滚动到屏幕外时,我很乐意实现自己的回收,但是不需要重新实现UIScrollView吗?

I'm brand-new to iPhone development, and still getting used to Objective-C, but I've been working in other languages (Java, C#, flex/actionscript, etc) for more than ten years, so I feel confident in my ability to get the work done, if only I had a better feel for the iPhone SDK and the common coding patterns for stuff like this. 我对iPhone开发是全新的,并且仍然习惯于Objective-C,但我已经使用其他语言(Java,C#,flex / actionscript等)十多年了,所以我对我有能力完成工作,只要我对iPhone SDK有更好的感觉,并为这样的东西提供常见的编码模式。 Is it just me, or does the SDK documentation really suck? 它只是我,还是SDK文档真的很糟糕?

Anyhow, thanks for your help! 无论如何,谢谢你的帮助!

Does your document have any semantic components other than each paragraph? 您的文档是否具有除每个段落之外的任何语义组件? If you already have some concept of sections or pages, I would recommend you render each one of those as an independent tablecell. 如果您已经有一些部分或页面的概念,我建议您将每个部分或页面渲染为独立的表格单元格。 It's pretty simple to create a tablecell that makes you forget you're actually looking at a UITableView. 创建一个让您忘记实际正在查看UITableView的表格单元非常简单。 All you would need to do is override drawRect: and setSelected: and setHighlighted: and tah dah! 你需要做的只是覆盖drawRect:和setSelected:和setHighlighted:和tah dah! No More cell dividers unless you want them. 除非您需要,否则不再使用细胞分裂 Furthermore you could do some nifty things by using a tableview as your base. 此外,您可以使用tableview作为基础来做一些漂亮的事情。 If you defined sections in the UITableView then you could have a nifty header that scrolls along as you're paging through your document. 如果你在UITableView中定义了部分,那么你可以有一个漂亮的标题,当你翻阅你的文档时它会滚动。 Another thing you could do is add a "jump to section" bar / a bookmarks menu, and that way you don't have to provide selection across the boundaries of sections. 您可以做的另一件事是添加“跳转到部分”栏/书签菜单,这样您就不必跨部分边界提供选择。

Massive copy paste blocks would be pretty painful on the system as well. 大规模的复制粘贴块在系统上也会非常痛苦。 Further, if you went through the trouble to provide this content you might not want to make it too easy for someone to copy it all at once... (Can't follow this line of thought more without more specifics on your project). 此外,如果您经历了提供此内容的麻烦,您可能不希望让某人一次性复制所有内容太容易...(如果没有更多关于项目的细节,则无法遵循这一思路)。

If you really do want to provide the copy paste options you could add buttons to each logical page or section that immediately selects and copies the whole section for the user's convenience. 如果您确实想要提供复制粘贴选项,则可以向每个逻辑页面或部分添加按钮,以便用户方便地立即选择和复制整个部分。 (Maybe with citation associated?) (也许引用相关?)

I recommend you lookup the UITableViewCell UITableViewDelegate and UITableViewDataSource in the SDK docs as those pages will significantly help if you choose to use this suggestion. 我建议您在SDK文档中查找UITableViewCell UITableViewDelegate和UITableViewDataSource,因为如果您选择使用此建议,这些页面将非常有用。

Just two random observations: 只是两个随机观察:

  • Can you afford to create a paging interface? 你能负担得起创建一个分页界面吗? (As opposed to “endless scrolling”.) It looks like a paging interface would be a lot easier on system resources. (与“无限滚动”相反。)看起来分页界面在系统资源上要容易得多。

  • The UIActionBar is actually the UIMenuController class. UIActionBar实际上是UIMenuController类。 The interface is a bit weird, as the menu is a singleton (wtf?), but I'm sure you'll have no trouble figuring it out. 界面有点奇怪,因为菜单是单身(wtf?),但我相信你可以毫不费力地搞清楚。

Hope that helps. 希望有所帮助。

Here's a potential solution, but I don't know if it's crazy. 这是一个潜在的解决方案,但我不知道它是否疯了。 Since I'm still so new to iPhone development, this might be a big no-no. 由于我仍然对iPhone开发这么新,这可能是一个很大的禁忌。

Anyhow, I had the idea to render each paragraph of the document (whose dimensions I've already precisely calculated) as a cell in a UITableView. 无论如何,我有想法将文档的每个段落(我已经精确计算过的维度)渲染为UITableView中的单元格。 Since UITableView already has mechanisms for cell recycling, I wouldn't have to implement that from scratch, and the document could be arbitrarily long without causing resource consumption problems. 由于UITableView已经具有单元回收机制,因此我不必从头开始实现,并且文档可以任意长,而不会导致资源消耗问题。

Of course, I'd want to get rid of the line separators between cells, since I want the UI to look like a document instead of a table. 当然,我想摆脱单元格之间的行分隔符,因为我希望UI看起来像文档而不是表格。

Or maybe I could render each page of the document (like a typical PDF, this is a paged-document format) as a table cell, and override the cell-separator graphic to look like a page boundary... 或者也许我可以将文档的每个页面(如典型的PDF,这是分页文档格式)渲染为表格单元格,并覆盖单元格分隔符图形看起来像页面边界...

But would it be possible to get rid of the default touch behavior within the table, and instead implement text-selection on the table cell contents? 但是有可能摆脱表中的默认触摸行为,而是在表格单元格内容上实现文本选择吗? Would it be completely impossible to implement text selection that crosses paragraph boundaries (between multiple table cells)? 是否完全不可能实现跨越段落边界的文本选择(在多个表格单元格之间)?

The UIWebView is a good choise, but we need another application to pre render the pages percisely using each font and each style sheet and store the rendring information into a database table: UIWebView是一个很好的选择,但我们需要另一个应用程序来使用每个字体和每个样式表预先渲染页面,并将rendring信息存储到数据库表中:

chapter_id int primary key, chapter_id int主键,
startlocation int, startlocation int,
end location int, 结束位置int,
fontsize int (or stylesheetname string) fontsize int(或stylesheetname字符串)

Using JavaScript we can calculate how many words fit in a div with out scrolling. 使用JavaScript,我们可以通过滚动来计算div中适合的单词数。

UIWebView is good as it provide rich content and it has selection and highlighting behavior. UIWebView非常好,因为它提供了丰富的内容,并且具有选择和突出显示行为。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM