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

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

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

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

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

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

спасибо!

2 ответов


что вам нужно, это собственный алгоритм компоновки, который принимает текст, измеряя его размер и сокращает его, пока он не вписывается в текстовый вид одной страницы. Затем начните с остальной части текста, то же самое для следующего текстового представления и так далее... После этого (или внутри алгоритма) вы упорядочиваете все результирующие текстовые представления на виде прокрутки (или в массиве, вы позже пролистываете с анимацией подкачки - Если вам нравится сырный). Я сделал аналогичную вещь, но с UILabels он также должен работать с textviews. Что вы нужно:NSString's - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size и rangeOfString:@" " 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

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

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

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