Как приложение iBooks форматирует текст на отдельных страницах? - PullRequest
11 голосов
/ 08 марта 2011

Глядя на приложение iBooks, мне стало интересно, как оно выполняет форматирование текста (возможно, очень простого txt-файла), чтобы оно НЕ было прокручиваться, а делилось на отдельные страницы.

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

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

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

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

Спасибо!

Ответы [ 2 ]

2 голосов
/ 08 марта 2011

Вам нужен собственный алгоритм компоновки, который берет текст, измеряет его размер и обрезает его, пока он не уместится в текстовое представление на одной странице.Затем начните с оставшейся части текста, то же самое для следующего текстового представления и т. Д. После этого (или внутри алгоритма) вы расположите все полученные текстовые представления в виде прокрутки (или в массиве, который вы позже пролистаетес анимацией подкачки - если вам это нравится, сырный).Я сделал похожую вещь, но с UILabels, он должен также работать с текстовыми представлениями.Вам нужно: NSString's - (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
0 голосов
/ 08 марта 2011

Я не видел исходный код, но я бы хотел гарантировать, что они используют CoreText Framework , чтобы выполнять пагинацию и рендеринг.Имейте в виду, однако, что когда он говорит «низкий уровень», это означает, что.Это фреймворк, который имеет дело с визуализацией персонажей напрямую.Такие вещи, как выбор и вставка символов (что вам, вероятно, понадобится для редактируемого текста), довольно сложны с CoreText.

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

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

...