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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27944781/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:20:46  来源:igfitidea点击:

How to change the tint color of the clear button on a UITextField

iosobjective-cswiftuibuttonuitextfield

提问by Niels Robben

I have an auto-generated clear button on my UITextfield, with the default blue tint color. I cannot change the tint color to white. I have tried modifying the storyboard and code without success, and I do not want to use a custom image.

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

How can I change the default clear button tint color without using a custom image?

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

clicked

点击

回答by Mikael Hellman

Here you go!

干得好!

A TintTextField.

一个 TintTextField。

Using no custom image, or added buttons etc.

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

Image of UITextField with white tint color for cancel button

用于取消按钮的带有白色色调的 UITextField 图像

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()
    }
 }

回答by matt

The reason you're having trouble doing this is that the clear button images are not tinted. They are just normal images.

您在执行此操作时遇到问题的原因是清晰的按钮图像没有着色。它们只是普通的图像。

The clear button is a button, internal to the UITextField. Like any button, it can have an image, and it does. In particular, it has twoimages: one for the Normal state, and one for the Highlighted state. The blue one to which the OP is objecting is the Highlighted image, and it can be captured by running this code at the time when the clear button is present:

清除按钮是一个按钮,位于 UITextField 内部。像任何按钮一样,它可以有一个图像,而且确实如此。特别是,它有两张图像:一张用于正常状态,一张用于突出显示状态。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
            }
        }
    }

Once you capture it, you will find that it is a 14x14 double-resolution tiff image, and here it is:

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

enter image description here

在此处输入图片说明

In theory, you can change the image to a different color, and you can assign it as the text view's clear button's image for the highlighted state. But in practice this is not at all easy to do, because the button is not always present; you cannot refer to it when it is absent (it isn't just invisible; it is actually not part of the view hierarchy at all, so there's no way to access it).

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

Moreover, there is no UITextField API to customize the clear button.

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

Thus, the simplest solution is what is advised here: create a button with custom Normal and Highlighted images and supply it as the UITextField's rightView. You then set the clearButtonModeto Never (since you are using the right view instead) and the rightViewModeto whatever you like.

因此,最简单的解决方案是这里建议的:创建一个带有自定义 Normal 和 Highlighted 图像的按钮,并将其作为 UITextField 的rightView. 然后您将 设置clearButtonMode为从不(因为您使用的是正确的视图)并将 设置rightViewMode为您喜欢的任何内容。

enter image description here

在此处输入图片说明

You will, of course, then have to detect a tap on this button and respond by clearing the text field's text; but this is easy to do, and is left as an exercise for the reader.

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

回答by MP23

Basing on @Mikael Hellman response I've prepared similar implementation of UITextField subclass for Objective-C. The only difference is that I allow to have separate colors for Normal and Highlighted states.

基于@Mikael Hellman 的回复,我为Objective-C 准备了类似的UITextField 子类实现。唯一的区别是我允许为 Normal 和 Highlighted 状态使用单独的颜色。

.h file

.h 文件

#import <UIKit/UIKit.h>


@interface TextFieldTint : UITextField

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

@end

.m file

.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

回答by Mohammad Sadiq

In Swift you can write the extension and use on any textfield in your project.

在 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)
    }
}
}

回答by CW0007007

For Swift 4, add this to a subclass of UITextField:

对于 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
            }
        }
    }
}

回答by Bonnke

Here is Swift 3 updated solution:

这是 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 = ""
    }
}

Enjoy ;)

享受 ;)

回答by CocoaBob

It could be even easier than the highest rated answer, available for iOS 7 and later.

它可能比评分最高的答案更容易,适用于 iOS 7 及更高版本。

@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

回答by Brody Robertson

You can use KVO to access the clear button and update it:

您可以使用 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];

    }

Note: This solution is not future proof - if Apple changes the implementation of of the clear button this will gracefully stop working.

注意:此解决方案不是面向未来的 - 如果 Apple 更改清除按钮的实现,这将正常停止工作。

回答by Rob Fahrni

If you use UIAppearance in your app you can set the tintColor for the clear button at runtime.

如果您在应用程序中使用 UIAppearance,则可以在运行时为清除按钮设置 tintColor。

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

At startup we call a class function in our AppDelegate that has a number of other controls that have their .appearance()configured in it.

在启动时,我们在 AppDelegate 中调用一个类函数,该函数具有许多其他.appearance()配置在其中的控件。

Suppose your class to set the appearance on your app is called Beautyifyyou would create something like this:

假设您的类在您的应用程序上设置外观被调用,Beautyify您将创建如下内容:

@objc class Beautify: NSObject {
    class func applyAppearance() {
        let tableViewAppearance = UITableView.appearance()
        tableViewAppearance.tintColor = .blue

        let textField = UITextField.appearance()
        textField.tintColor = .green
    }
}

Then inside of AppDelegate didFinishLaunchingWithOptionsjust call it.

然后在 AppDelegate 内部didFinishLaunchingWithOptions调用它。

Beautify.applyAppearance()

Beautify.applyAppearance()

It's a great way to configure the appearance of things in your application all at the same time.

这是同时配置应用程序中事物外观的好方法。

回答by Kosrat D. Ahmad

You can use your custom icon and it works in iOS 11,

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

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