如何更改UITextField上清除按钮的色调颜色

Nie*_*ben 50 objective-c uibutton uitextfield ios swift

我的UITextfield上有一个自动生成的清除按钮,默认为蓝色色调.我无法将色调颜色更改为白色.我试过修改故事板和代码没有成功,我不想使用自定义图像.

如何在不使用自定义图像的情况下更改默认的清除按钮色调?

点击

Mik*_*man 73

干得好!

一个TintTextField.

不使用自定义图像或添加按钮等.

在此输入图像描述

class TintTextField: UITextField {

     var tintedClearImage: UIImage?

     required init(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
       self.setupTintColor()
     }

     override init(frame: CGRect) {
       super.init(frame: frame)
       self.setupTintColor()
     }

     func setupTintColor() {
       self.borderStyle = UITextField.BorderStyle.roundedRect
       self.layer.cornerRadius = 8.0
       self.layer.masksToBounds = true
       self.layer.borderColor = self.tintColor.cgColor
       self.layer.borderWidth = 1.5
       self.backgroundColor = .clear
       self.textColor = self.tintColor
     }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.tintClearImage()
    }

    private func tintClearImage() {
        for view in subviews {
            if view is UIButton {
                let button = view as! UIButton
                if let image = button.image(for: .highlighted) {
                    if self.tintedClearImage == nil {
                        tintedClearImage = self.tintImage(image: image, color: self.tintColor)
                    }
                    button.setImage(self.tintedClearImage, for: .normal)
                    button.setImage(self.tintedClearImage, for: .highlighted)
                }
            }
        }
    }

    private func tintImage(image: UIImage, color: UIColor) -> UIImage {
        let size = image.size

        UIGraphicsBeginImageContextWithOptions(size, false, image.scale)
        let context = UIGraphicsGetCurrentContext()
        image.draw(at: .zero, blendMode: CGBlendMode.normal, alpha: 1.0)

        context?.setFillColor(color.cgColor)
        context?.setBlendMode(CGBlendMode.sourceIn)
        context?.setAlpha(1.0)

        let rect = CGRect(x: CGPoint.zero.x, y: CGPoint.zero.y, width: image.size.width, height: image.size.height)
        UIGraphicsGetCurrentContext()?.fill(rect)
        let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return tintedImage ?? UIImage()
    }
 }
Run Code Online (Sandbox Code Playgroud)

  • 在iOS 11中不再有效.此解决方案的按钮alpha错误 (7认同)
  • 看起来很有希望.你能提供Objective-C版本吗? (4认同)
  • 如果我心情愉快,我可以阅读Objective-C,但请相信我,你不想看我写Objective-C.一种新的iOS,并加入了与Swift的火车.:) (2认同)

mat*_*att 23

您无法做到这一点的原因是清晰的按钮图像没有着色.它们只是普通的图像.

清除按钮是UITextField内部的按钮.像任何按钮一样,它可以有一个图像,它可以.特别是,它有两个图像:一个用于Normal状态,一个用于Highlighted状态.OP反对的蓝色图像是突出显示的图像,可以通过在清除按钮出现时运行此代码来捕获它:

    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
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

一旦你捕获它,你会发现它是一个14x14的双分辨率tiff图像,这里是:

在此输入图像描述

理论上,您可以将图像更改为其他颜色,并可以将其指定为文本视图的清除按钮的图像以显示突出显示的状态.但实际上这并不容易,因为按钮并不总是存在; 当它不存在时你不能引用它(它不仅是不可见的;它实际上根本不是视图层次结构的一部分,因此无法访问它).

此外,没有UITextField API来自定义清除按钮.

因此,最简单的解决办法是什么,建议在这里:创建一个按钮,自定义标准,并强调图像,并提供其作为的UITextField的rightView.然后,您将设置clearButtonMode为从不(因为您正在使用正确的视图)和rightViewMode任何您喜欢的.

在此输入图像描述

当然,您必须检测到点击此按钮并通过清除文本字段的文本进行响应; 但这很容易做到,并留给读者练习.


MP2*_*P23 15

基于@Mikael Hellman的响应,我为Objective-C准备了类似的UITextField子类实现.唯一的区别是我允许为正常状态和突出显示状态分别使用颜色.

.h文件

#import <UIKit/UIKit.h>


@interface TextFieldTint : UITextField

-(void) setColorButtonClearHighlighted:(UIColor *)colorButtonClearHighlighted;
-(void) setColorButtonClearNormal:(UIColor *)colorButtonClearNormal;

@end
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)


Moh*_*diq 14

在Swift中,您可以编写扩展并在项目的任何文本字段中使用.

extension UITextField {
    @objc 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
    }

    @objc func clear(_ sender : AnyObject) {
    if delegate?.textFieldShouldClear?(self) == true {
        self.text = ""
        sendActions(for: .editingChanged)
    }
}
}
Run Code Online (Sandbox Code Playgroud)


小智 13

斯威夫特 5 解决方案:

   if let clearButton = yourTextField.value(forKey: "_clearButton") as? UIButton {
       let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate)
       clearButton.setImage(templateImage, for: .normal)
       clearButton.tintColor = .darkGray
   }
Run Code Online (Sandbox Code Playgroud)


CW0*_*007 11

对于Swift 4,将其添加到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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在iOS 12中不适合我.清除按钮不会改变颜色. (3认同)

Tai*_* Le 7

这个想法是通过 key 获取清晰的按钮clearButton,然后使用模式重新渲染清晰的图像alwaysTemplate

[Swift 4.2] 刚刚在这里进行了扩展UITextField

extension UITextField {
    var clearButton: UIButton? {
        return value(forKey: "clearButton") as? UIButton
    }

    var clearButtonTintColor: UIColor? {
        get {
            return clearButton?.tintColor
        }
        set {
            let image =  clearButton?.imageView?.image?.withRenderingMode(.alwaysTemplate)
            clearButton?.setImage(image, for: .normal)
            clearButton?.tintColor = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但此解决方案的问题是清除按钮的图像是nil在您调用设置色调颜色时的。

所以对于每个人来说,使用RxSwift清晰按钮来观察图像。

import RxSwift

extension UITextField {
    var clearButton: UIButton? {
        return value(forKey: "clearButton") as? UIButton
    }

    var clearButtonTintColor: UIColor? {
        get {
            return clearButton?.tintColor
        }
        set {
            _ = rx.observe(UIImage.self, "clearButton.imageView.image")
                .takeUntil(rx.deallocating)
                .subscribe(onNext: { [weak self] _ in
                    let image = self?.clearButton?.imageView?.image?.withRenderingMode(.alwaysTemplate)
                    self?.clearButton?.setImage(image, for: .normal)
                })
            clearButton?.tintColor = newValue
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Bro*_*son 5

您可以使用KVO访问清除按钮并进行更新:

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

    }
Run Code Online (Sandbox Code Playgroud)

注意:此解决方案不是未来证明 - 如果Apple更改了清除按钮的实现,这将优雅地停止工作.

  • 这不是真的.该应用程序可能崩溃.如果您在登录表单上有此文本框,则用户突然无法再使用您的应用程序 (3认同)

Kos*_*mad 5

您可以使用自定义图标,它适用于 iOS 11,

searchBar.setImage(UIImage(named: "ic_clear"), for: .clear, state: .normal)
Run Code Online (Sandbox Code Playgroud)