Как приложение iBooks форматирует текст на отдельных страницах?

Глядя на приложение iBooks, мне было интересно, как это сделать, чтобы форматировать текст (возможно, очень простой файл txt), чтобы он НЕ ПРОСМОТРЕН, а делился на отдельные страницы.

Я хотел бы добиться того же, но только с редактируемым текстом.

Где мне нужно начинать? UITextView не работает, поскольку он прокручивается. Даже если я присвоил свойству pagingEnabled значение YES, он не будет выполнять задание.

Кажется, мне нужно ограничить количество текста, которое я могу разместить на определенной странице. Есть ли функция LIMIT для ввода UITextView? Мне нужно было бы ограничить количество LINES (а не символов), поскольку они будут показаны на полном экране iPhone (я думаю, вы можете поместить около 20 строк в зависимости от размера шрифта).

Любая помощь будет оценена! Поскольку я новичок, я особенно ценю образцы, в которых используются подобные методы.

Спасибо!

Ответ 1

Что вам нужно - это собственный алгоритм компоновки, который принимает текст, измеряет его размер и сокращает его до тех пор, пока он не будет входить в одностраничный текстовый вид. Затем начните с остальной части текста, то же самое для следующего текстового представления и т.д. После этого (или внутри алгоритма) вы упорядочиваете все результирующие текстовые представления в режиме прокрутки (или в массиве, вы позже переходите через с пейджинговыми анимациями - если вам нравится это cheesy). Я сделал аналогичную вещь, но с UILabels, она также должна работать с текстовыми изображениями. Вам нужно: NSString - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size и r angeOfString:@" " options:NSBackwardsSearch (поиск пространств слов) и substringFromIndex: соответственно. substringToIndex:

Если вам нужна дополнительная информация, просто отправьте комментарий.

ИЗМЕНИТЬ

Привет, следующий код не проверен, но содержит большинство из того, что вам нужно (надеюсь), но может содержать некоторые ошибки, особенно когда речь заходит о рекурсии... Я исправил идею BackWardsSearch, потому что это может занять долгое время вырезать длинный текст. То, что я полностью проигнорировал - и это может быть очень сложно, - это повторное рендеринг при редактировании. Но в любом случае, вот код. Это контроллер представления, предполагаемый старыми 4 членами (файл заголовка не опубликован):

  UIView *editableBook;
  NSMutableArray *content;
  int currentPage;
  UIFont *font;

И это сам контроллер:

//
//  EditableBookController.m
//
//  Created by Kai on 09.03.11.
//

#import "EditableBookController.h"


@implementation EditableBookController

-(id)initWithText:(NSString *)text
{
  if (self=[super init]) 
  {
    font = [UIFont fontWithName:@"SomeFont" size:12];
    content = [[NSMutableArray alloc]init];
    [self cutInPages:text];
    currentPage = 0;  
  }
  return self;
}

- (void)loadView 
{
  self.view = [[UIView alloc] initWithFrame:CGRectMake(.0, .0, 768., 1024.)];//assuming portrait only ...
  editableBook = [[UIView alloc]initWithFrame:self.view.bounds];//could be a scroll view in alternate approach
  UISwipeGestureRecognizer *flipper = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextOrPrevious:)];
  [editableBook addGestureRecognizer:flipper];
  [flipper release];
  [self.view addSubview:editableBook];
  UITextView *textView = [[UITextView alloc]initWithText:[content objectAtIndex:currentPage]];
  textView.frame = editableBook.bounds;
  textView.font = font;
  textView.tag = 23;
  [editableBook addSubview:textView];
  [textView release];
}

-(void)nextOrPrevious:(id)sender
{
  UISwipeGestureRecognizer *flipper = (UISwipeGestureRecognizer*)sender;
  if(flipper.direction == UISwipeGestureRecognizerDirectionLeft)
  {
    [self next];
  }
  else if(flipper.direction == UISwipeGestureRecognizerDirectionRight)
  {
    [self previous];
  }
}

-(void)next
{
  if(currentPage == content.count - 1)
  {
    return;
  }
  currentPage++;
  UIView *fromView = [editableBook viewWithTag:23];
  UIView *toView =  [[UITextView alloc]initWithText:[content objectAtIndex:currentPage]];
  toView.frame = editableBook.bounds;
  toView.tag = 23;
  [UIView transitionWithView:editableBook duration:0.2 options:UIViewAnimationTransitionFlipFromRight
   animations:^
   {
     [fromView removeFromSuperview];
     [editableBook addSubview:toView];
   }
   completion:NULL];
}

-(void)previous
{
  if(currentPage == 0)
  {
    return;
  }
  currentPage--;
  UIView *fromView = [editableBook viewWithTag:23];
  UIView *toView =  [[UITextView alloc]initWithText:[content objectAtIndex:currentPage]];
  toView.frame = editableBook.bounds;
  toView.tag = 23;
  [UIView transitionWithView:editableBook duration:0.2 options:UIViewAnimationTransitionFlipFromLeft
   animations:^
   {
     [fromView removeFromSuperview];
     [editableBook addSubview:toView];
   }
   completion:NULL];
}

-(void)cutInPages:(NSString *)text
{
  NSRange whereToCut = whereToCut = [text rangeOfString:@" "];
  NSString *pageText = [text substringToIndex:whereToCut.location];
  NSString *rest = [text substringFromIndex:whereToCut.location];;
  CGFloat height = 0;
  while (height<1024.) 
  {
    NSRange whereToCut = [rest rangeOfString:@" "];
    NSString *wordOfRest = [rest substringToIndex:whereToCut.location];
    pageText = [NSString stringWithFormat:@"%@%@", pageText, wordOfRest];
    rest = [rest substringFromIndex:whereToCut.location];;
    CGSize size = [pageText sizeWithFont:font
                      constrainedToSize:CGSizeMake(768., 10000) 
                          lineBreakMode:UILineBreakModeWordWrap];
    height = size.height;
  }
  if(height>1024.)
  {
    //TODO cut the last word of pageText and prepend to the eest
  }
  [content addObject:pageText];
  if([rest length] > 0)
  {
    [self cutInPages:rest];
  }
}

- (void)dealloc 
{
  [editableBook release];
  [content release];
  [super dealloc];
}


@end

Ответ 2

Я не видел исходный код, но я был бы готов гарантировать, что они используют CoreText framework для выполнения своих разбиение на страницы и рендеринг. Однако следует предупредить, что когда он говорит "низкий уровень", это значит. Это структура, которая напрямую связана с визуализацией символов. Например, в CoreText довольно сложно использовать набор символов и вставку (который вы, вероятно, хотите для редактируемого текста) довольно сложно.

Я бы рекомендовал использовать NSString методы рисования и калибровки, которые являются частью структуры UIKit. Но даже тогда вам придется сделать немало работы, чтобы получить этот функционал. Я не думаю, что UIKit предлагает текстовое редактирование, которое не прокручивается. Мы предполагаем, что если вы хотите отредактировать текст, он будет иметь произвольную длину, что означает, что мы помещаем его в прокручиваемый контейнер (так, чтобы он мог быть любой длины).

Вкратце, если вы новичок, я бы рекомендовал работать над чем-то другим. То, о чем вы просите, нелегко сделать.:)