wake-up-neo.com

So ändern Sie die Farbtonfarbe der Schaltfläche "Löschen" in einem UITextField

Ich habe in meinem UITextfield eine automatisch generierte Löschtaste mit der Standardfarbe für den blauen Farbton. Ich kann die Tönungsfarbe nicht in Weiß ändern. Ich habe versucht, das Storyboard und den Code ohne Erfolg zu ändern, und ich möchte kein benutzerdefiniertes Bild verwenden.

Wie kann ich die Standardfarbtonfarbe für die Löschschaltfläche ändern, ohne ein benutzerdefiniertes Bild zu verwenden?

clicked

47
Niels Robben

Bitte schön! 

Ein TintTextField.

Verwenden Sie kein benutzerdefiniertes Bild oder hinzugefügte Schaltflächen usw.

enter image description here

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
}
69
Mikael Hellman

Der Grund, warum Sie Probleme damit haben, besteht darin, dass die Bilder der klaren Schaltfläche nicht gefärbt sind. Sie sind nur normale Bilder.

Die Schaltfläche "Löschen" ist eine Schaltfläche innerhalb des UITextField. Wie jede Taste kann es ein Bild haben, aber es hat auch ein Bild. Insbesondere gibt es zwei Bilder: eines für den Normalzustand und eines für den hervorgehobenen Zustand. Das blaue Objekt, gegen das das OP Einspruch erhebt, ist das hervorgehobene Bild. Es kann durch Ausführen dieses Codes zu dem Zeitpunkt erfasst werden, zu dem die Schaltfläche "Löschen" vorhanden ist:

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

Sobald Sie es aufgenommen haben, werden Sie feststellen, dass es sich um ein 14x14-Bild mit doppelter Auflösung handelt, und hier ist es:

enter image description here

Theoretisch können Sie das Bild in eine andere Farbe ändern und es als hervorgehobenes Bild der Schaltfläche für die Textansicht für den hervorgehobenen Status zuweisen. In der Praxis ist dies jedoch nicht ganz einfach, da der Button nicht immer vorhanden ist. Sie können sich nicht auf sie beziehen, wenn sie nicht vorhanden ist (sie ist nicht nur unsichtbar; sie ist überhaupt nicht Teil der Ansichtshierarchie, daher gibt es keine Möglichkeit, darauf zuzugreifen).

Darüber hinaus gibt es keine UITextField-API zum Anpassen der Schaltfläche "Löschen".

Daher ist die einfachste Lösung Folgendes: hier : Erstellen Sie eine Schaltfläche mit benutzerdefinierten Normal- und hervorgehobenen Bildern, und geben Sie diese als UITextFields rightView an. Dann setzen Sie clearButtonMode auf Nie (da Sie stattdessen die rechte Ansicht verwenden) und rightViewMode auf das, was Sie möchten.

enter image description here

Sie müssen dann natürlich ein Tippen auf diese Schaltfläche erkennen und darauf reagieren, indem Sie den Text des Textfelds löschen. Dies ist jedoch einfach zu tun und bleibt dem Leser als Übung überlassen.

22
matt

Basierend auf der Antwort von @Mikael Hellman habe ich eine ähnliche Implementierung der UITextField-Unterklasse für Objective-C vorbereitet. Der einzige Unterschied ist, dass ich für die Zustände Normal und Hervorgehoben unterschiedliche Farben zulasse.

.h Datei

#import <UIKit/UIKit.h>


@interface TextFieldTint : UITextField

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

@end

.m Datei

#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
15
MP23

Für Swift 4 fügen Sie dies einer Unterklasse von UITextField hinzu: 

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
            }
        }
    }
}
10
CW0007007

In Swift können Sie die Erweiterung schreiben und in jedem Textfeld Ihres Projekts verwenden. 

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)
    }
}
10
Mohammad Sadiq

Sie können KVO verwenden, um auf die Schaltfläche "Löschen" zuzugreifen und diese zu aktualisieren:

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

    }

Hinweis: Diese Lösung ist nicht zukunftssicher. Wenn Apple die Implementierung der Schaltfläche "Löschen" ändert, wird die Funktion nicht mehr ordnungsgemäß ausgeführt.

5
Brody Robertson

Hier ist die aktualisierte Lösung von 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 = ""
    }
}

Genießen ;)

3
Bonnke

Wenn Sie UIAppearance in Ihrer App verwenden, können Sie zur Laufzeit die tintColor für die Schaltfläche zum Löschen festlegen.

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

Beim Start rufen wir eine Klassenfunktion in unserem AppDelegate auf, die eine Reihe anderer Steuerelemente enthält, deren .appearance() konfiguriert ist.

Angenommen, Ihre Klasse, mit der Sie das Erscheinungsbild Ihrer App festlegen, heißt Beautyify Sie würden so etwas erstellen:

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

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

Dann rufen Sie es in AppDelegate didFinishLaunchingWithOptions einfach auf.

Beautify.applyAppearance()

Auf diese Weise können Sie die Darstellung von Dingen in Ihrer Anwendung gleichzeitig konfigurieren.

3
Rob Fahrni

Es könnte sogar einfacher sein als die am besten bewertete Antwort, die für iOS 7 und höher verfügbar ist.

@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
3
CocoaBob

Dies funktionierte für mich mit Objective-C. Ich habe Stücke aus anderen Threads zu diesem Thema gezogen und kam zu dieser Lösung:

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

In Swift 3: Das funktioniert für mich

    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
    }
1
Aqib Mumtaz

Swift 4, das funktioniert für mich (ändern Sie die tintColor in Ihre eigene Farbe):

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

Sie müssen es in viewDidLayoutSubviews() aufrufen, um sicherzustellen, dass es schließlich aufgerufen wird, da es verschiedene clearButtonMode-Situationen gibt (always, whileEditing usw.). Ich glaube, dass diese Knöpfe faul erstellt werden. Also nenne es in viewDidLoad() meistens nicht.

1
aunnnn

Swift 4, saubere und prägnante Unterklasse

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)
        }
    }
}
1
3vangelos

Sie können Ihr benutzerdefiniertes Symbol verwenden und es funktioniert in iOS 11, 

searchBar.setImage(UIImage(named: "ic_clear"), for: .clear, state: .normal)
1
Kosrat D. Ahmad

Die Idee ist, die Schaltfläche zum Löschen mit der Taste clearButton abzurufen und das Bild im Modus alwaysTemplate erneut zu rendern.

[Swift 4.2] Habe gerade eine Erweiterung für UITextField gemacht:

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

Das Problem bei dieser Lösung ist jedoch, dass das Bild der Schaltfläche zum Zeitpunkt des Aufrufs zum Festlegen der Tönungsfarbe nil lautet.

Also verwendet jeder RxSwift, um das Bild mit der Schaltfläche "Löschen" zu betrachten.

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
        }
    }
}
1
Tai Le

Die Antwort von Matt oben ist richtig. Die Schaltfläche "Löschen" in UITextField ist nicht vorhanden, wenn sie nicht angezeigt wird. Man kann versuchen, gleich darauf zuzugreifen, nachdem UITextField seine layoutSubviews durchführt und das Vorhandensein der Schaltfläche überprüft. Die einfachste Methode besteht darin, eine UITextField zu subklassifizieren, layoutSubviews zu überschreiben und wenn die Schaltfläche zum ersten Mal angezeigt wird, das ursprüngliche Bild zu speichern ( s) für spätere Verwendung und dann bei späteren Aufführungen einen Farbton auftragen.

Im Folgenden zeige ich Ihnen, wie Sie dies mit der Erweiterung tun, weil Sie auf diese Weise Ihren benutzerdefinierten Farbton auf jedes UITextField anwenden können, einschließlich derer, die in fertigen Klassen wie UISearchBar verschachtelt sind.

Viel Spaß und Daumen aufgeben, wenn es Ihnen gefällt :)

Swift 3.2

Hier ist die Haupterweiterung:

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

}

Hier sind zusätzliche Ausschnitte, die im obigen Code verwendet werden:

Netter Wrapper für alle Dinge, die Sie objektbezogen erreichen möchten:

class Wrapper<T> {
    var underlying: T?

    init(_ underlying: T?) {
        self.underlying = underlying
    }
}

Eine Erweiterung für die Suche nach verschachtelten Unteransichten eines beliebigen Typs:

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
    }

}

Erweiterung für UIImage, um eine Tönungsfarbe anzuwenden

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
    }

}

... und zum Schluss Swizzling-Sachen:

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

}
1
MonsterSale

Nachdem ich alle Antworten und Möglichkeiten durchgegangen war, habe ich diese einfache und direkte Lösung gefunden.

-(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];
1
GurPreet_Singh

Erstellen Sie diese Methode.

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
}

Und implementieren Sie Ihr UITextFieldDelegate , indem Sie die Methode von textFieldDidEndEditing aufrufen. Damit ändern Sie Ihr Bild, bevor Sie Text erstellen.

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

Einzelheiten

  • Xcode Version 10.1 (10B61)
  • Schnell 4.2

Lösung

import UIKit

extension UISearchBar {

    func getTextField() -> UITextField? { return value(forKey: "searchField") as? UITextField }

    func setClearButton(color: UIColor) {
        getTextField()?.setClearButton(color: color)
    }
}

extension UITextField {

    private class ClearButtonImage {
        static private var _image: UIImage?
        static private var semaphore = DispatchSemaphore(value: 1)
        static func getImage(closure: @escaping (UIImage?)->()) {
            DispatchQueue.global(qos: .userInteractive).async {
                semaphore.wait()
                DispatchQueue.main.async {
                    if let image = _image { closure(image); semaphore.signal(); return }
                    guard let window = UIApplication.shared.windows.first else { semaphore.signal(); return }
                    let searchBar = UISearchBar(frame: CGRect(x: 0, y: -200, width: UIScreen.main.bounds.width, height: 44))
                    window.rootViewController?.view.addSubview(searchBar)
                    searchBar.text = "txt"
                    searchBar.layoutIfNeeded()
                    _image = searchBar.getTextField()?.getClearButton()?.image(for: .normal)
                    closure(_image)
                    searchBar.removeFromSuperview()
                    semaphore.signal()
                }
            }
        }
    }

    func setClearButton(color: UIColor) {
        ClearButtonImage.getImage { [weak self] image in
            guard   let image = image,
                    let button = self?.getClearButton() else { return }
            button.imageView?.tintColor = color
            button.setImage(image.withRenderingMode(.alwaysTemplate), for: .normal)
        }
    }

    func getClearButton() -> UIButton? { return value(forKey: "clearButton") as? UIButton }
}

Volle probe

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let textField = UITextField(frame: CGRect(x: 20, y: 20, width: 200, height: 44))
        view.addSubview(textField)
        textField.backgroundColor = .lightGray
        textField.clearButtonMode = .always
        textField.setClearButton(color: .red)

        let searchBar = UISearchBar(frame: CGRect(x: 20, y: 80, width: 200, height: 44))
        view.addSubview(searchBar)
        searchBar.backgroundColor = .lightGray
        searchBar.setClearButton(color: .red)
    }
}

Ergebnis

 enter image description here

0

Sie können meine Bibliothek LSCategories verwenden, um dies mit einer Zeile zu tun:

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

Es verwendet KEINE private API, es wird NICHT nach Original UIButton in der UITextField-Subviews-Hierarchie gesucht, und es ist NICHT erforderlich, UITextField als andere Antworten hier zu subklassifizieren. Stattdessen wird die RightView-Eigenschaft verwendet, um die Schaltfläche zum Löschen des Systems zu imitieren. Daher müssen Sie sich keine Sorgen machen, dass die Funktion in Zukunft nicht mehr funktioniert, wenn Apple etwas ändert. Es funktioniert auch in Swift.

0
Leszek Szary

Ich habe viele Antworten ausprobiert, bis ich diese Lösung in @Mikael Hellman-Lösung gefunden habe. Diese Lösung verwendet Swift 4.2 .

Die Idee ist die gleiche:

Verwenden Sie kein benutzerdefiniertes Bild oder hinzugefügte Schaltflächen usw.

Und mit einer benutzerdefinierten Klasse, die UITextField erweitert.

class TintClearTextField: UITextField {

    private var updatedClearImage = false

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

    private func tintClearImage() {
        if updatedClearImage { return }

        if let button = self.value(forKey: "clearButton") as? UIButton,
            let image = button.image(for: .highlighted)?.withRenderingMode(.alwaysTemplate) {
            button.setImage(image, for: .normal)
            button.setImage(image, for: .highlighted)
            button.tintColor = .white

            updatedClearImage = true
        }
    }
}

Sie brauchen nicht updatedClearImage, aber bedenken Sie, dass Sie alle Logiken in jeder Zeichenergänzung ausführen.

Ich muss nicht einmal tintColor einstellen, um das gewünschte Ergebnis zu erhalten. Kommentieren Sie diese Zeile, bevor Sie Ihre Farbe einstellen.

Wenn es nicht wie gewünscht aussieht, ändern Sie den .white mit der gewünschten Farbe, und das ist alles.

PS .: Ich habe ein Feld, das bereits in meinem Ausgangsbildschirm ausgefüllt ist. Dazu ändert sich nur ein Farbwechsel mit tintColor Millisekunden nach dem Anzeigen der Standardelementfarbe, wie bei einem "Glitch". Ich könnte es nicht besser machen, aber da ich nicht tintColor verwende, ist das für mich in Ordnung.

Ich hoffe es hilft :)

0
Endy Silveira