tutorial page control ios xcode text uiscrollview scroll-paging

ios - page - Cómo separar cadenas para UIScrollView/UITextView en función del tamaño del marco



uipageviewcontroller (2)

Actualmente estoy tratando de leer en un canal RSS y separar el texto largo y paragrafiado en un UIScrollView con paginación habilitada. Necesito separar el texto en diferentes páginas, también ajustar lo que encajará en cada página y separar la cadena como tal. No estoy seguro de si hay un estándar de qué hacer esto y supongo que así es como la mayoría de las aplicaciones de lectura RSS separan su información en varias páginas. ¿Alguien sabe cómo hacer frente a esto? No quería mirar letra por letra hasta que el texto no se ajustara y continuar.

editar:

Este es un buen comienzo, pero el código de ejemplo se topa con los problemas que estaba tratando de evitar y no sé cómo moverme. Este rango calcula incorrectamente para UITextView. Cambio la fuente y tal como se ve a continuación. Todo está intentando ser calculado dentro de - (NSRange) visibleRangeOfTextView: (UITextView *) textView. Este método es llamado por - (void) adjustTextDisplay que es llamado por una clase externa después de configurar el UITextView. No tengo idea de por qué establecer el tamaño del contenido en el tamaño del marco de la pantalla no restringe la vista (como se muestra a continuación) ni sé por qué este método devuelve la longitud completa de la cadena como el rango.


A partir de iOS 7, hay una solución mucho más elegante para esto utilizando TextKit que he incluido en el código de ejemplo a continuación. La idea es permitir que el gestor de diseño de TextKit maneje la separación de los glifos y exponga todo correctamente. Esto evita cortar palabras a mitad de camino y una tonelada de flexibilidad:

class BookView: UIScrollView { var bookMarkup: NSAttributedString! private let layoutManager = NSLayoutManager() override func layoutSubviews() { super.layoutSubviews() if layoutManager.textContainers.count == 0 { buildFrames() } } func buildFrames() { let textStorage = NSTextStorage(attributedString: bookMarkup) textStorage.addLayoutManager(layoutManager) var range = NSMakeRange(0, 0) var containerIndex = 0 while NSMaxRange(range) < layoutManager.numberOfGlyphs { let textViewRect = frameForViewAtIndex(containerIndex) let containerSize = CGSizeMake(CGRectGetWidth(textViewRect), CGRectGetHeight(textViewRect) - 16) //UITextView adds an 8 margin above and below the container so we take that into consideration here with the 16. heightTracksTextView causes a performance hit when adding multiple containers... so we don''t do that instead let textContainer = NSTextContainer(size: containerSize) layoutManager.addTextContainer(textContainer) let textView = UITextView(frame: textViewRect, textContainer: textContainer) addSubview(textView) containerIndex++ range = layoutManager.glyphRangeForTextContainer(textContainer) } contentSize = CGSize(width: CGRectGetWidth(bounds) / 2 * CGFloat(containerIndex), height: CGRectGetHeight(bounds)) pagingEnabled = true } private func frameForViewAtIndex(index: Int) -> CGRect { var textViewRect = CGRect(origin: CGPointZero, size: CGSize(width: CGRectGetWidth(bounds)/2, height: CGRectGetHeight(bounds))) textViewRect = CGRectInset(textViewRect, 10, 20) textViewRect = CGRectOffset(textViewRect, CGRectGetWidth(bounds) / 2 * CGFloat(index), 0) return textViewRect } }


En lugar de cálculos iterativos intensos, establecí el texto completo (comenzando desde el final de la página anterior) en la vista de texto y obtengo la última posición del carácter que se muestra . Entonces es fácil realizar una búsqueda rápida hacia atrás para truncar la palabra / oración.

Tengo la siguiente solución, una parte complicada de omitir la última línea parcialmente visualizada para evitar el desplazamiento y hacer que se vea mejor. Aún necesita mover endCutIndex para que sea envoltorio de palabra o frase.

El proyecto base con el localizador pero no las vistas de texto se toma de aquí

- (void)viewDidLoad { [super viewDidLoad]; NSString * fullText = @"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."; pageControlBeingUsed = NO; int pageNumber = 0; UIFont * theFont = [UIFont boldSystemFontOfSize:30]; const CGSize charSize = [@"A" sizeWithFont:theFont]; while (fullText.length > 0) { CGRect frame; frame.origin.x = self.scrollView.frame.size.width * (pageNumber++); frame.origin.y = 0; frame.size = self.scrollView.frame.size; UIView *subview = [[UIView alloc] initWithFrame:frame]; UITextView * textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; textView.font = theFont; [subview addSubview:textView]; [textView release]; textView.text = fullText; CGRect bounds = textView.bounds; // - charSize.height to skip a partially visible line // - charSize.width*2 to skip annoying character still displayed at partially visible line CGPoint endPoint = CGPointMake(CGRectGetMaxX(bounds) - charSize.width*2, CGRectGetMaxY(bounds) - charSize.height); UITextPosition *start = [textView characterRangeAtPoint:bounds.origin].start; UITextPosition *end = [textView characterRangeAtPoint:endPoint].end; const int startCutIndex = [textView offsetFromPosition:textView.beginningOfDocument toPosition:start]; const int endCutIndex = [textView offsetFromPosition:textView.beginningOfDocument toPosition:end]; NSString * cutText = [fullText substringToIndex:endCutIndex]; textView.text = cutText; fullText = [fullText substringFromIndex:endCutIndex]; [self.scrollView addSubview:subview]; [subview release]; NSLog(@"Page (1-total) %d, start text index %d, end text index %d /ntext:%@", pageNumber, startCutIndex, endCutIndex, cutText); } const int totalPages = pageNumber; self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * totalPages, self.scrollView.frame.size.height); self.pageControl.currentPage = 0; self.pageControl.numberOfPages = totalPages; }

Aquí hay un poco del archivo .h:

@interface FCContentViewController : UIViewController <UIScrollViewDelegate, UITextViewDelegate>{ UIPageControl *pageControl; NSString *trunkedString; UITextView *bodyText; } @property (nonatomic, retain) UIScrollView *scrollView; @property (nonatomic, retain) NSString *bodyTextString;