2012-08-01 3 views
5

Desidero disegnare il testo in un UITextField con un'ombra. Per fare questo, ho sottoclasse UITextField, e implementato il metodo drawTextInRect: come segue:UITextField shadow non viene visualizzato durante la modifica

- (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];  
} 

Questa grande opera per quando il campo di testo non sta modificando, ma non appena inizia la modifica, l'ombra scompare. C'è qualcosa che mi manca?

+0

che ho visto questo prima su Mac OS X, e in questo caso è stato perché l'editor campo non afferrare l'ombra attributi dal 'NSTextField' e, quindi, non ha mostrato l'ombra. Non so se ci sono editor di campo in iOS, ma ho pensato di commentare. – Vervious

+0

Ho fatto qualche ricerca su google e non sembra che UITextField usi editor di campo, quindi ignora il mio commento precedente. – Vervious

+0

ti rendi conto che aggiungere un'ombra esterna al testo così piccolo su iOS renderà il testo quasi illeggibile. –

risposta

0

Si potrebbe provare a fare il disegno dell'etichetta da soli. Rimuovi

[super drawTextInRect:rect] 

E invece disegnare la propria etichetta. Non ho provato questo ma potrebbe essere simile a questa:

// 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

Ecco il codice per il seguente componente

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 

paio di cose da prendere in considerazione:

  • Vuoi impostare borderStyle su none, altrimenti ti ritroverai con UIKit mettere subviews nel vostro campo di testo
  • A seconda della versione di Xcode si potrebbe desiderare di collegare QuartzCore e #import <QuartzCore/QuartzCore.h>
  • Per l'aspetto più complesso è ancora possibile proprietà utilizzo ombra dello strato e spostare il codice di disegno in sé nella drawRect: metodo, ma jake_hetfield aveva ragione se si ignorare drawRect non si vuole chiamare super, soprattutto alla fine del metodo
  • per quanto riguarda il testo disegno (si può vedere che si attacca al vicino alla componente bordi), si dispone di un separato drawTextInRect: e drawPlaceholderInRect: metodo che disegna il testo e segnaposto rispettivamente
  • È possibile utilizzare il metodo UIColor per colori e chiamare proprietà CGColor, rende il codice più leggibile e più facile da mantenere

Speranza che aiuta!

0

Smetti di chiamare super e visualizza il testo da solo.

1

Ispirato risposta @jake_hetfield ho creato una consuetudine UITextField che utilizza un etichetta interna per fare il disegno, check it out:

ShadowTextField file 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 file di

#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 

Ecco come lo si utilizza nel vostro controller di 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

Rivolgersi ai provato con le proprietà ombra standard del CALayer? di solito è abbastanza ed è molto più semplice. Provare qualcosa di simile con un UITextField regolare:

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); 

è necessario importare QuartzCore prima ovviamente!

#import <QuartzCore/QuartzCore.h> 
+0

Un'ombra per * testo *, non l'intera vista. – conradev

+0

ummm giusto! il mio male, mi dispiace! –