teñir tabla pintarse pelo como colores color claro chocolate cafe cabello ios objective-c swift uibutton uitextfield

ios - tabla - Cómo cambiar el color del tinte del botón de borrar en un UITextField



como teñir el pelo color chocolate (18)

Tengo un botón de borrado generado automáticamente en el campo de mi UIT, con el color de tinte azul predeterminado. No puedo cambiar el color del tinte a blanco. He intentado modificar el guión gráfico y el código sin éxito, y no quiero usar una imagen personalizada.

¿Cómo puedo cambiar el color de tinte del botón de borrar predeterminado sin usar una imagen personalizada?


¡Aqui tienes!

A TintTextField.

Usando ninguna imagen personalizada, o botones agregados etc.

class TintTextField: UITextField { var tintedClearImage: UIImage? required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupTintColor() } override init(frame: CGRect) { super.init(frame: frame) setupTintColor() } func setupTintColor() { clearButtonMode = UITextFieldViewMode.WhileEditing borderStyle = UITextBorderStyle.RoundedRect layer.cornerRadius = 8.0 layer.masksToBounds = true layer.borderColor = tintColor.CGColor layer.borderWidth = 1.5 backgroundColor = UIColor.clearColor() textColor = tintColor } override func layoutSubviews() { super.layoutSubviews() tintClearImage() } private func tintClearImage() { for view in subviews as! [UIView] { if view is UIButton { let button = view as! UIButton if let uiImage = button.imageForState(.Highlighted) { if tintedClearImage == nil { tintedClearImage = tintImage(uiImage, tintColor) } button.setImage(tintedClearImage, forState: .Normal) button.setImage(tintedClearImage, forState: .Highlighted) } } } } } func tintImage(image: UIImage, color: UIColor) -> UIImage { let size = image.size UIGraphicsBeginImageContextWithOptions(size, false, image.scale) let context = UIGraphicsGetCurrentContext() image.drawAtPoint(CGPointZero, blendMode: CGBlendMode.Normal, alpha: 1.0) CGContextSetFillColorWithColor(context, color.CGColor) CGContextSetBlendMode(context, CGBlendMode.SourceIn) CGContextSetAlpha(context, 1.0) let rect = CGRectMake( CGPointZero.x, CGPointZero.y, image.size.width, image.size.height) CGContextFillRect(UIGraphicsGetCurrentContext(), rect) let tintedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return tintedImage }


Aquí está la solución actualizada Swift 3:

extension UITextField { func modifyClearButtonWithImage(image : UIImage) { let clearButton = UIButton(type: .custom) clearButton.setImage(image, for: .normal) clearButton.frame = CGRect(x: 0, y: 0, width: 15, height: 15) clearButton.contentMode = .scaleAspectFit clearButton.addTarget(self, action: #selector(self.clear(sender:)), for: .touchUpInside) self.rightView = clearButton self.rightViewMode = .whileEditing } func clear(sender : AnyObject) { self.text = "" } }

Disfrutar;)


Basándome en la respuesta de @Mikael Hellman, he preparado una implementación similar de la subclase UITextField para Objective-C. La única diferencia es que permito tener colores separados para los estados Normal y Resaltado.

archivo .h

#import <UIKit/UIKit.h> @interface TextFieldTint : UITextField -(void) setColorButtonClearHighlighted:(UIColor *)colorButtonClearHighlighted; -(void) setColorButtonClearNormal:(UIColor *)colorButtonClearNormal; @end

archivo .m

#import "TextFieldTint.h" @interface TextFieldTint() @property (nonatomic,strong) UIColor *colorButtonClearHighlighted; @property (nonatomic,strong) UIColor *colorButtonClearNormal; @property (nonatomic,strong) UIImage *imageButtonClearHighlighted; @property (nonatomic,strong) UIImage *imageButtonClearNormal; @end @implementation TextFieldTint -(void) layoutSubviews { [super layoutSubviews]; [self tintButtonClear]; } -(void) setColorButtonClearHighlighted:(UIColor *)colorButtonClearHighlighted { _colorButtonClearHighlighted = colorButtonClearHighlighted; } -(void) setColorButtonClearNormal:(UIColor *)colorButtonClearNormal { _colorButtonClearNormal = colorButtonClearNormal; } -(UIButton *) buttonClear { for(UIView *v in self.subviews) { if([v isKindOfClass:[UIButton class]]) { UIButton *buttonClear = (UIButton *) v; return buttonClear; } } return nil; } -(void) tintButtonClear { UIButton *buttonClear = [self buttonClear]; if(self.colorButtonClearNormal && self.colorButtonClearHighlighted && buttonClear) { if(!self.imageButtonClearHighlighted) { UIImage *imageHighlighted = [buttonClear imageForState:UIControlStateHighlighted]; self.imageButtonClearHighlighted = [[self class] imageWithImage:imageHighlighted tintColor:self.colorButtonClearHighlighted]; } if(!self.imageButtonClearNormal) { UIImage *imageNormal = [buttonClear imageForState:UIControlStateNormal]; self.imageButtonClearNormal = [[self class] imageWithImage:imageNormal tintColor:self.colorButtonClearNormal]; } if(self.imageButtonClearHighlighted && self.imageButtonClearNormal) { [buttonClear setImage:self.imageButtonClearHighlighted forState:UIControlStateHighlighted]; [buttonClear setImage:self.imageButtonClearNormal forState:UIControlStateNormal]; } } } + (UIImage *) imageWithImage:(UIImage *)image tintColor:(UIColor *)tintColor { UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0); CGContextRef context = UIGraphicsGetCurrentContext(); CGRect rect = (CGRect){ CGPointZero, image.size }; CGContextSetBlendMode(context, kCGBlendModeNormal); [image drawInRect:rect]; CGContextSetBlendMode(context, kCGBlendModeSourceIn); [tintColor setFill]; CGContextFillRect(context, rect); UIImage *imageTinted = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageTinted; } @end


Crea este método.

func configureClearButtonColor() { guard let clearButton = textField.value(forKey: "_clearButton") as? UIButton else { return } let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate) clearButton.setImage(templateImage, for: .normal) clearButton.setImage(templateImage, for: .highlighted) clearButton.tintColor = .white }

E implemente su UITextFieldDelegate , en el campo de textFieldDidEndEditing, llame al método. Eso cambia tu imagen antes de crear algún texto.

func textFieldDidEndEditing(_ textField: UITextField) { configureClearButtonColor() }


Después de revisar todas las respuestas y posibilidades, he encontrado esta solución simple y directa.

-(void)updateClearButtonColor:(UIColor *)color ofTextField:(UITextField *)textField { UIButton *btnClear = [textField valueForKey:@"_clearButton"]; UIImage * img = [btnClear imageForState:UIControlStateNormal]; if (img) { UIImage * renderingModeImage = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [btnClear setImage:renderingModeImage forState:UIControlStateNormal]; //-- Add states you want to update [btnClear setImage:renderingModeImage forState:UIControlStateSelected]; } [btnClear setTintColor:color]; } [self updateClearButtonColor:[UIColor whiteColor] ofTextField:self.textField];


En SWIFT 3: esto está funcionando para mí.

if let clearButton = self.textField.value(forKey: "_clearButton") as? UIButton { // Create a template copy of the original button image let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate) // Set the template image copy as the button image clearButton.setImage(templateImage, for: .normal) clearButton.setImage(templateImage, for: .highlighted) // Finally, set the image color clearButton.tintColor = .white }


En Swift puede escribir la extensión y usarla en cualquier campo de texto en su proyecto.

extension UITextField { func modifyClearButton(with image : UIImage) { let clearButton = UIButton(type: .custom) clearButton.setImage(image, for: .normal) clearButton.frame = CGRect(x: 0, y: 0, width: 15, height: 15) clearButton.contentMode = .scaleAspectFit clearButton.addTarget(self, action: #selector(UITextField.clear(_:)), for: .touchUpInside) rightView = clearButton rightViewMode = .whileEditing } func clear(_ sender : AnyObject) { self.text = "" sendActions(for: .editingChanged) } }


Esto me funcionó utilizando object-C. Saqué piezas de otros hilos sobre este tema y encontré esta solución:

UIButton *btnClear = [self.textFieldUserID valueForKey:@"clearButton"]; [btnClear setImage:[UIImage imageNamed:@"facebookLoginButton"] forState:UIControlStateNormal];


La razón por la que tiene problemas para hacer esto es que las imágenes del botón no están teñidas. Solo son imágenes normales.

El botón de borrar es un botón, interno al UITextField. Como cualquier botón, puede tener una imagen, y la tiene. En particular, tiene dos imágenes: una para el estado Normal y otra para el estado Resaltado. El azul al que se opone el OP es la imagen resaltada, y puede capturarse ejecutando este código en el momento en que está presente el botón de borrar:

let tf = self.tf // the text view for sv in tf.subviews as! [UIView] { if sv is UIButton { let b = sv as! UIButton if let im = b.imageForState(.Highlighted) { // im is the blue x } } }

Una vez que lo capture, encontrará que es una imagen tiff de doble resolución de 14x14, y aquí está:

En teoría, puede cambiar la imagen a un color diferente, y puede asignarla como imagen clara del botón de la vista de texto para el estado resaltado. Pero en la práctica esto no es fácil de hacer, porque el botón no siempre está presente; no puede referirse a él cuando está ausente (no es solo invisible, sino que en realidad no forma parte de la jerarquía de vistas, por lo que no hay forma de acceder a ella).

Además, no hay una API de UITextField para personalizar el botón de borrado.

Por lo tanto, la solución más sencilla es la que se recomienda here : crear un botón con imágenes personalizadas normales y resaltadas y proporcionarlo como rightView del rightView . A continuación, establezca el clearButtonMode en Nunca (ya que en su lugar está utilizando la vista correcta) y el rightViewMode de rightViewMode en lo que desee.

Por supuesto, tendrá que detectar un toque en este botón y responder borrando el texto del campo de texto; pero esto es fácil de hacer, y se deja como un ejercicio para el lector.


Para Swift 4, agregue esto a una subclase de UITextField:

import UIKit class CustomTextField: UITextField { override func layoutSubviews() { super.layoutSubviews() for view in subviews { if let button = view as? UIButton { button.setImage(button.image(for: .normal)?.withRenderingMode(.alwaysTemplate), for: .normal) button.tintColor = .white } } } }


Podría ser incluso más fácil que la respuesta con la calificación más alta, disponible para iOS 7 y versiones posteriores.

@interface MyTextField @end @implementation MyTextField - (void)layoutSubviews { [super layoutSubviews]; for (UIView *subView in self.subviews) { if ([subView isKindOfClass:[UIButton class]]) { UIButton *button = (UIButton *)subView; [button setImage:[[button imageForState:UIControlStateNormal] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; button.tintColor = self.tintColor; } } } @end


Puede usar las categorías LSCategories mi biblioteca para hacer eso con una línea:

[textField lsSetClearButtonWithColor:[UIColor redColor] mode:UITextFieldViewModeAlways];

NO utiliza ninguna API privada, NO busca UIButton original en la jerarquía de subvistas de UITextField y NO requiere la subclase UITextField como otras respuestas aquí. En su lugar, utiliza la propiedad rightView para imitar el botón de borrado del sistema, por lo que no debe preocuparse de que dejará de funcionar en el futuro si Apple cambia algo. Funciona en Swift también.


Puedes usar KVO para acceder al botón de borrar y actualizarlo:

UIButton *clearButton = [myTextField valueForKey:@"_clearButton"] if([clearButton respondsToSelector:@selector(setImage:forState:)]){ //ensure that the app won''t crash in the future if _clearButton reference changes to a different class instance [clearButton setImage:[UIImage imageNamed:@"MyImage.png"] forState:UIControlStateNormal]; }

Nota: esta solución no está preparada para el futuro: si Apple cambia la implementación del botón de borrar, esto dejará de funcionar correctamente.


Puedes usar tu icono personalizado y funciona en iOS 11,

searchBar.setImage(UIImage(named: "ic_clear"), for: .clear, state: .normal)


Respuesta publicada por Matt arriba es correcta. El botón de borrar dentro de UITextField no existe si no se muestra. Uno puede intentar acceder a él inmediatamente después de que UITextField realice sus presentaciones de subvistas y verifique la existencia del botón. El enfoque más sencillo es subclasificar un UITextField , anular layoutSubviews y, si se muestra el botón por primera vez, almacenar su (s) imagen (es) original (es) para su uso posterior, y luego, durante cualquier presentación posterior, aplicar un tinte.

A continuación, le muestro cómo hacer esto utilizando la extensión porque de esta manera puede aplicar su tinte personalizado a cualquier UITextField, incluidos los que están anidados en clases listas como UISearchBar.

Diviértete y da los pulgares para arriba si te gusta :)

Swift 3.2

Aquí está la extensión principal:

import UIKit extension UITextField { private struct UITextField_AssociatedKeys { static var clearButtonTint = "uitextfield_clearButtonTint" static var originalImage = "uitextfield_originalImage" } private var originalImage: UIImage? { get { if let cl = objc_getAssociatedObject(self, &UITextField_AssociatedKeys.originalImage) as? Wrapper<UIImage> { return cl.underlying } return nil } set { objc_setAssociatedObject(self, &UITextField_AssociatedKeys.originalImage, Wrapper<UIImage>(newValue), .OBJC_ASSOCIATION_RETAIN) } } var clearButtonTint: UIColor? { get { if let cl = objc_getAssociatedObject(self, &UITextField_AssociatedKeys.clearButtonTint) as? Wrapper<UIColor> { return cl.underlying } return nil } set { UITextField.runOnce objc_setAssociatedObject(self, &UITextField_AssociatedKeys.clearButtonTint, Wrapper<UIColor>(newValue), .OBJC_ASSOCIATION_RETAIN) applyClearButtonTint() } } private static let runOnce: Void = { Swizzle.for(UITextField.self, selector: #selector(UITextField.layoutSubviews), with: #selector(UITextField.uitextfield_layoutSubviews)) }() private func applyClearButtonTint() { if let button = UIView.find(of: UIButton.self, in: self), let color = clearButtonTint { if originalImage == nil { originalImage = button.image(for: .normal) } button.setImage(originalImage?.tinted(with: color), for: .normal) } } func uitextfield_layoutSubviews() { uitextfield_layoutSubviews() applyClearButtonTint() } }

Aquí hay fragmentos adicionales utilizados en el código anterior:

Un bonito envoltorio para cualquier cosa a la que le gustaría acceder a objetos:

class Wrapper<T> { var underlying: T? init(_ underlying: T?) { self.underlying = underlying } }

Una extensión para encontrar subvistas anidadas de cualquier tipo:

extension UIView { static func find<T>(of type: T.Type, in view: UIView, includeSubviews: Bool = true) -> T? where T: UIView { if view.isKind(of: T.self) { return view as? T } for subview in view.subviews { if subview.isKind(of: T.self) { return subview as? T } else if includeSubviews, let control = find(of: type, in: subview) { return control } } return nil } }

Extensión para UIImage para aplicar un color de tinte.

extension UIImage { func tinted(with color: UIColor) -> UIImage? { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) color.set() self.withRenderingMode(.alwaysTemplate).draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } }

... y finalmente cosas Swizzling:

class Swizzle { class func `for`(_ className: AnyClass, selector originalSelector: Selector, with newSelector: Selector) { let method: Method = class_getInstanceMethod(className, originalSelector) let swizzledMethod: Method = class_getInstanceMethod(className, newSelector) if (class_addMethod(className, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { class_replaceMethod(className, newSelector, method_getImplementation(method), method_getTypeEncoding(method)) } else { method_exchangeImplementations(method, swizzledMethod) } } }


Si usa UIAppearance en su aplicación, puede configurar el tintColor para el botón de borrar en tiempo de ejecución.

let textField = UITextField.appearance() textField.tintColor = .greenColor()

En el inicio, llamamos a una función de clase en nuestro AppDelegate que tiene una serie de otros controles que tienen su .appearance() configurado en ella.

Supongamos que su clase para establecer el aspecto de su aplicación se llama Beautyify , crearía algo como esto:

@objc class Beautify: NSObject { class func applyAppearance() { let tableViewAppearance = UITableView.appearance() tableViewAppearance.tintColor = .blueColor() let textField = UITextField.appearance() textField.tintColor = .greenColor() } }

Luego, dentro de AppDelegate didFinishLaunchingWithOptions simplemente didFinishLaunchingWithOptions .

Beautify.applyAppearance()

Es una excelente manera de configurar la apariencia de las cosas en su aplicación al mismo tiempo.


Swift 4, Subclase limpio y conciso

import UIKit class CustomTextField: UITextField { override func layoutSubviews() { super.layoutSubviews() for view in subviews where view is UIButton { (view as! UIButton).setImage(<MY_UIIMAGE>, for: .normal) } } }


Swift 4, esto funciona para mí (cambia el tintColor a tu propio color):

var didSetupWhiteTintColorForClearTextFieldButton = false private func setupTintColorForTextFieldClearButtonIfNeeded() { // Do it once only if didSetupWhiteTintColorForClearTextFieldButton { return } guard let button = yourTextField.value(forKey: "_clearButton") as? UIButton else { return } guard let icon = button.image(for: .normal)?.withRenderingMode(.alwaysTemplate) else { return } button.setImage(icon, for: .normal) button.tintColor = .white didSetupWhiteTintColorForClearTextFieldButton = true } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() setupTintColorForTextFieldClearButtonIfNeeded() }

viewDidLayoutSubviews() llamarlo en viewDidLayoutSubviews() para asegurarse de que finalmente se llame, porque hay diferentes situaciones de clearButtonMode ( always , whileEditing , etc.). Creo que estos botones están creados perezosamente. Así que llámalo en viewDidLoad() mayoría no funciona.