2012-08-01 20 views
5

Quiero dibujar el texto en un UITextField con una sombra. Con el fin de hacer esto, he subclase UITextField, y puesto en práctica el método drawTextInRect: de la siguiente manera:UITextField shadow no se muestra al editar

- (void)drawTextInRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Create shadow color 
    float colorValues[] = {0.21875, 0.21875, 0.21875, 1.0}; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGColorRef shadowColor = CGColorCreate(colorSpace, colorValues); 
    CGColorSpaceRelease(colorSpace); 

    // Create shadow 
    CGSize shadowOffset = CGSizeMake(2, 2); 
    CGContextSetShadowWithColor(context, shadowOffset, 0, shadowColor); 
    CGColorRelease(shadowColor); 

    // Render text 
    [super drawTextInRect:rect];  
} 

Esto funciona muy bien para cuando el campo de texto no está editando, pero tan pronto como comienza la edición, la sombra desaparece. ¿Hay algo que me falta?

+0

que he visto esto antes en Mac OS X, y en ese caso fue debido a que el editor de campo no agarrar atribuye la sombra del 'NSTextField' y por lo tanto no se presentó a la sombra. No sé si hay editores de campo en iOS, pero pensé en comentar. – Vervious

+0

Hice algunas búsquedas en Google y no parece que UITextFields use editores de campo, por lo que ignoro mi comentario anterior. – Vervious

+0

te das cuenta de que agregar una sombra paralela al texto tan pequeño en iOS hará que el texto sea casi ilegible. –

Respuesta

0

Puede intentar hacer el dibujo de la etiqueta usted mismo. Eliminar

[super drawTextInRect:rect] 

Y, en su lugar, dibujar su propia etiqueta. No he probado esto, pero podría ser algo como esto:

// Declare a label as a member in your class in the .h file and a property for it: 
UILabel *textFieldLabel; 
@property (nonatomic, retain) UILabel *textFieldLabel; 

// Draw the label 
- (void)drawTextInRect:(CGRect)rect { 
    if (self.textFieldLabel == nil) { 
     self.textFieldLabel = [[[UILabel alloc] initWithFrame:rect] autorelease]; 
     [self.view addSubview:myLabel]; 
    } 

    self.textFieldLabel.frame = rect; 
    self.textFieldLabel.text = self.text; 

    /** Set the style you wish for your label here **/ 
    self.textFieldLabel.shadowColor = [UIColor grayColor]; 
    self.textFieldLabel.shadowOffset = CGSizeMake(2,2); 
    self.textFieldLabel.textColor = [UIColor blueColor]; 

    // Do not call [super drawTextInRect:myLabel] method if drawing your own text 
} 
1

Este es el código para el componente siguiente

enter image description here

@interface AZTextField() 
- (void)privateInitialization; 
@end 

@implementation AZTextField 

static CGFloat const kAZTextFieldCornerRadius = 3.0; 

- (id)initWithFrame:(CGRect)frame 
{ 

    self = [super initWithFrame:frame]; 
    if (!self) return nil; 
    [self privateInitialization]; 
    return self; 
} 

// In case you decided to use it in a nib 
- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    if (!self) return nil; 
    [self privateInitialization]; 
    return self; 
} 

- (void)privateInitialization 
{ 
    self.borderStyle = UITextBorderStyleNone; 

    self.layer.masksToBounds = NO; 
    self.layer.shadowColor = [UIColor blackColor].CGColor; 
    self.layer.shadowOffset = CGSizeMake(0.0f, 5.0f); 
    self.layer.shadowOpacity = 0.5f; 

    self.layer.backgroundColor = [UIColor whiteColor].CGColor; 
    self.layer.cornerRadius = 4; 

    // This code is better to be called whenever size of the textfield changed, 
    // so if you plan to do that you can add an observer for bounds property 
    UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kAZTextFieldCornerRadius]; 
    self.layer.shadowPath = shadowPath.CGPath; 
} 

@end 

par de cosas a tener en cuenta:

  • Desea establecer borderStyle en none, de lo contrario terminará con UIKit poner subvistas en su campo de texto
  • Dependiendo de la versión de Xcode es posible que desee vincular QuartzCore y para #import <QuartzCore/QuartzCore.h>
  • Para el aspecto más complejo todavía se puede propiedades uso de sombra de la capa y mover el código de dibujo en sí en el drawRect: método, pero jake_hetfield tenía razón si anular drawRect usted no desea llamar estupendo, especialmente en el extremo del método
  • en cuanto a la elaboración de texto (se puede ver que se pega a cerca del componente fronteras), tiene unpor separadodrawTextInRect: y drawPlaceholderInRect: método que se basa el texto y marcador de posición, respectivamente
  • Puede utilizar el método de UIColor colores y llamar a la propiedad CGColor, que hace que el código sea más legible y más fácil de mantener

Espero que ayude!

0

Deje de llamar a super y renderice el texto usted mismo.

1

Inspirado en respuesta @jake_hetfield creé una costumbre UITextField que utiliza una etiqueta interna para hacer el dibujo, comprobar que funciona:

ShadowTextField archivo .h

#import <UIKit/UIKit.h> 

@interface ShadowTextField : UITextField 

// properties to change the shadow color & offset 
@property (nonatomic, retain) UIColor *textShadowColor; 
@property (nonatomic) CGSize textShadowOffset; 

- (id)initWithFrame:(CGRect)frame 
       font:(UIFont *)font 
      textColor:(UIColor *)textColor 
     shadowColor:(UIColor *)shadowColor 
     shadowOffset:(CGSize)shadowOffset; 

@end 

ShadowTextField.m archivo

#import "ShadowTextField.h" 

@interface ShadowTextField() 
@property (nonatomic, retain) UILabel *internalLabel; 
@end 

@implementation ShadowTextField 
@synthesize internalLabel = _internalLabel; 
@synthesize textShadowColor = _textShadowColor; 
@synthesize textShadowOffset = _textShadowOffset; 

- (id)initWithFrame:(CGRect)frame 
       font:(UIFont *)font 
      textColor:(UIColor *)textColor 
     shadowColor:(UIColor *)shadowColor 
     shadowOffset:(CGSize)shadowOffset 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 

     // register to my own text changes notification, so I can update the internal label 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(handleUITextFieldTextDidChangeNotification) 
                name:UITextFieldTextDidChangeNotification 
                object:nil]; 

     self.font = font; 
     self.textColor = textColor; 

     self.textShadowColor = shadowColor; 
     self.textShadowOffset = shadowOffset; 
    } 
    return self; 
} 

// when the user enter text we update the internal label 
- (void)handleUITextFieldTextDidChangeNotification 
{ 
    self.internalLabel.text = self.text; 

    [self.internalLabel sizeToFit]; 
} 

// init the internal label when first needed 
- (UILabel *)internalLabel 
{ 
    if (!_internalLabel) { 
     _internalLabel = [[UILabel alloc] initWithFrame:self.bounds]; 
     [self addSubview:_internalLabel]; 

     _internalLabel.font = self.font; 
     _internalLabel.backgroundColor = [UIColor clearColor]; 
    } 
    return _internalLabel; 
} 

// override this method to update the internal label color 
// and to set the original label to clear so we wont get two labels 
- (void)setTextColor:(UIColor *)textColor 
{ 
    [super setTextColor:[UIColor clearColor]]; 

    self.internalLabel.textColor = textColor; 
} 

// override this method to update the internal label text 
- (void)setText:(NSString *)text 
{ 
    [super setText:text]; 

    self.internalLabel.text = self.text; 

    [self.internalLabel sizeToFit]; 
} 

- (void)setTextShadowColor:(UIColor *)textShadowColor 
{ 
    self.internalLabel.shadowColor = textShadowColor; 
} 

- (void)setTextShadowOffset:(CGSize)textShadowOffset 
{ 
    self.internalLabel.shadowOffset = textShadowOffset; 
} 

- (void)drawTextInRect:(CGRect)rect { 
    // don't draw anything 
    // we have the internal label for that... 
} 

- (void)dealloc { 
    [_internalLabel release]; 
    [_textShadowColor release]; 

    [super dealloc]; 
} 

@end 

Aquí es cómo lo usa en su controlador de vista

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    ShadowTextField *textField = [[ShadowTextField alloc] initWithFrame:CGRectMake(0, 0, 320, 30) 
                    font:[UIFont systemFontOfSize:22.0] 
                   textColor:[UIColor whiteColor] 
                  shadowColor:[UIColor redColor] 
                  shadowOffset:CGSizeMake(0, 1) ] ; 
    textField.text = @"This is some text";  
    textField.backgroundColor = [UIColor blackColor]; 
    [self.view addSubview:textField]; 
} 
0

Que su tratado con las propiedades de sombra estándar de la CALayer? por lo general es suficiente y es mucho más simple. Pruebe algo como esto con un UITextField regular:

self.inputContainer.layer.shadowColor=[UIColor blackColor].CGColor; 
self.inputContainer.layer.shadowRadius=8.0f; 
self.inputContainer.layer.cornerRadius=8.0f; 
self.inputContainer.layer.shadowOffset=CGSizeMake(0, 4); 

¡Primero debe importar QuartzCore, por supuesto!

#import <QuartzCore/QuartzCore.h> 
+0

Una sombra para el * texto *, no toda la vista. – conradev

+0

ummm correcto! mi mal, lo siento! –

Cuestiones relacionadas