2010-05-14 15 views

Respuesta

9

lo logré subclasificando UIView y reemplazando el método drawRect: así:

#define TXT_VIEW_INSETS 8.0 // The default insets for a UITextView is 8.0 on all sides 

@implementation NumberedTextView 

@synthesize lineNumbers; 
@synthesize delegate; 

- (id)initWithFrame:(CGRect)frame { 
    if ((self = [super initWithFrame:frame])) { 
     [self setContentMode:UIViewContentModeRedraw]; 

     internalScrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 
     [internalScrollView  setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 
     [internalScrollView  setBackgroundColor:[UIColor clearColor]]; 
     [internalScrollView   setClipsToBounds:YES]; 
     [internalScrollView   setScrollsToTop:YES]; 
     [internalScrollView   setContentSize:self.bounds.size]; 
     [internalScrollView   setContentMode:UIViewContentModeLeft]; 
     [internalScrollView    setDelegate:self]; 
     [internalScrollView    setBounces:NO]; 

     internalTextView = [[UITextView alloc] initWithFrame:self.bounds]; 
     [internalTextView setAutocapitalizationType:UITextAutocapitalizationTypeNone]; 
     [internalTextView  setAutocorrectionType:UITextAutocorrectionTypeNo]; 
     [internalTextView  setSpellCheckingType:UITextSpellCheckingTypeNo]; 
     [internalTextView  setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 
     [internalTextView   setBackgroundColor:[UIColor clearColor]]; 
     [internalTextView   setClipsToBounds:YES]; 
     [internalTextView   setScrollsToTop:NO]; 
     [internalTextView    setContentMode:UIViewContentModeLeft]; 
     [internalTextView    setDelegate:self]; 
     [internalTextView     setBounces:NO]; 

     [internalScrollView addSubview:internalTextView]; 
     [self addSubview:internalScrollView]; 
    } 
    return self; 
} 

- (void)drawRect:(CGRect)rect { 
    if (self.lineNumbers) { 
     [[internalTextView textColor] set]; 
     CGFloat xOrigin, yOrigin, width/*, height*/; 
     uint numberOfLines = (internalTextView.contentSize.height + internalScrollView.contentSize.height)/internalTextView.font.lineHeight; 
     for (uint x = 0; x < numberOfLines; ++x) { 
      NSString *lineNum = [NSString stringWithFormat:@"%d:", x]; 

      xOrigin = CGRectGetMinX(self.bounds); 

      yOrigin = ((internalTextView.font.pointSize + abs(internalTextView.font.descender)) * x) + TXT_VIEW_INSETS - internalScrollView.contentOffset.y; 

      width = [lineNum sizeWithFont:internalTextView.font].width; 
//   height = internalTextView.font.lineHeight; 

      [lineNum drawAtPoint:CGPointMake(xOrigin, yOrigin) withFont:internalTextView.font]; 
     } 

     CGRect tvFrame = [internalTextView frame]; 
     tvFrame.size.width = CGRectGetWidth(internalScrollView.bounds) - width; 
     tvFrame.size.height = MAX(internalTextView.contentSize.height, CGRectGetHeight(internalScrollView.bounds)); 
     tvFrame.origin.x = width; 
     [internalTextView setFrame:tvFrame]; 
     tvFrame.size.height -= TXT_VIEW_INSETS; // This fixed a weird content size problem that I've forgotten the specifics of. 
     [internalScrollView setContentSize:tvFrame.size]; 
    } 
} 

#pragma mark - UITextView Delegate 

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { 
    [self setNeedsDisplay]; 
    return YES; 
} 

- (void)textViewDidChange:(UITextView *)textView { 
    [self setNeedsDisplay]; 
} 

- (void)textViewDidChangeSelection:(UITextView *)textView { 
    [self setNeedsDisplay]; 
} 

#pragma mark - UIScrollView Delegate 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    [self setNeedsDisplay]; 
} 
+0

Gracias por compartir el código. Para su información, para otras personas que lo intentan, no tiene en cuenta el ajuste de palabras, por lo que los números de línea son solo un recuento visual de las líneas, no líneas reales en el texto. – Philosophistry

+0

@Philosophistry Gracias por señalar esto; Me olvidé de mencionar eso. Este código no trata con el ajuste de línea porque en el método 'layoutSubviews' me aseguro de que' internalScrollView' y 'internalTextView' sean lo suficientemente anchos para ajustarse a la línea de texto más larga sin ajustar (de hecho, ajusto el ancho de los marcos cuando' internalTextView' el contenido de texto cambia, pero las comprobaciones dobles de 'layoutSubviews' para asegurarse de que sean lo suficientemente amplias). Esto fue intencional porque tratar de hacer funcionar la numeración de líneas con envoltura hubiera sido un gran dolor de cabeza :). – chown

+0

Tengo un problema extraño: mientras continúo, presione volver en la vista de uitext, se convierte en un espacio grande entre el número de línea y la posición del cursor/cursor usando el mismo código que aquí. ¿Algunas ideas? Gracias –

-2

No hay nada incorporado para esto. Tendrás que hacerlo tú mismo.

+8

Podría ser más fácil a la subclase UITextView y editar los métodos de dibujo allí, aunque probablemente será una tarea desde cualquier ángulo. – JoePasq

Cuestiones relacionadas