Customize UITextfield of the UISearchbar - iOS
Asked Answered
C

9

13

I'm trying to customize the textfield for the UISearchbar. The picture below shows my half done work. strong text

I have subclasses the UISearchbar and called it from my view controller. I'm trying to remove those dark gray lines from the textfield. Below is the implementation of the UISearchbar adding to subview of the viewcontroller.

searchbar = [[SearchBar alloc] initWithFrame:CGRectMake(35,78, 250, 17)];
searchbar.backgroundColor = [UIColor clearColor];
searchbar.layer.borderColor = [[UIColor clearColor] CGColor];
searchbar.layer.borderWidth = 0;

for(UIView *view in searchbar.subviews){
    if([view isKindOfClass:[UITextField class]]){
        UITextField *tf= (UITextField *)view;
        tf.layer.borderColor = [[UIColor clearColor] CGColor];
        tf.delegate = self;
        break;
    }
}
[self.view addSubview:searchbar];
searchbar.delegate = self;

UISearchBar subclass:

   - (id)initWithFrame:(CGRect)frame
  {
   self = [super initWithFrame:frame];
if (self) {
      // Initialization code
     }
     return self;
}

-(void)layoutSubviews{
     UITextField *searchField;
     [[[self subviews] objectAtIndex:0] removeFromSuperview];
     [self setTintColor:[UIColor clearColor]];
     self.clipsToBounds = YES;
     NSUInteger numViews = [self.subviews count];
     for(int i = 0; i < numViews; i++) {
        if([[self.subviews objectAtIndex:i] isKindOfClass:[UITextField class]]) { 
            searchField = [self.subviews objectAtIndex:i];
             searchField.leftViewMode = UITextFieldViewModeNever;
             searchField.backgroundColor = [UIColor clearColor];

        }


    }
    if(!(searchField == nil)) {            
        searchField.backgroundColor = [UIColor clearColor];
        searchField.textColor = [UIColor blackColor];
        searchField.frame = CGRectMake(self.frame.origin.x,self.frame.origin.y,self.frame.size.width,self.frame.size.height-10);

        [searchField setBorderStyle:UITextBorderStyleRoundedRect];

    }

    [super layoutSubviews];

}

I'm trying to achive something like this: The textfield should not have any boundaries. The icons are flattened UIImageView.

enter image description here

Charterhouse answered 19/10, 2012 at 4:12 Comment(0)
V
51

This is an easy way to get textfield from UISearchBar subview hierarchy and set its properties as needed like

  UITextField *txfSearchField = [searchbar valueForKey:@"_searchField"];
[txfSearchField setBackgroundColor:[UIColor whiteColor]];
    [txfSearchField setLeftView:UITextFieldViewModeNever];
    [txfSearchField setBorderStyle:UITextBorderStyleRoundedRect];
    txfSearchField.layer.borderWidth = 8.0f; 
    txfSearchField.layer.cornerRadius = 10.0f;
        txfSearchField.layer.borderColor = [UIColor clearColor].CGColor;
Viscus answered 19/10, 2012 at 5:39 Comment(8)
the icons are part of the UIImageview like i said. Its the textfield that I'm worried about. Those dark gray lines are to be removed.Thanks for the answer tho. The icons are already removed from the search bar.Charterhouse
Thanks! I used this to change the keyboard for the search using UITextField *txfSearchField = [_searchBar valueForKey:@"_searchField"]; [txfSearchField setKeyboardType:UIKeyboardTypeNumberPad];Glittery
is there a way to change the text inset of this textfield?Tangled
@Viscus [searchbar valueForKey:@"_searchField"] is returning nil. Any idea why?Picot
@VigneshPT you have to put (UITextField *)[searchbar valueForKey:@"_searchField"]Filiate
@Filiate typecasting nil would still be nilPicot
it is crashed on iOS 13Lucianolucias
In iOS 13 you get the SearchTextField as so: UITextField *search = searchBar.searchTextFieldHylomorphism
H
12

Use the following if you don't want to use undocumented features or use an image:

CGSize size = CGSizeMake(30, 30);
// create context with transparent background
UIGraphicsBeginImageContextWithOptions(size, NO, 1);

// Add a clip before drawing anything, in the shape of an rounded rect
[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0,0,30,30)
                            cornerRadius:2.0] addClip];
[[UIColor whiteColor] setFill];

UIRectFill(CGRectMake(0, 0, size.width, size.height));
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[self.searchBar setSearchFieldBackgroundImage:image forState:UIControlStateNormal];
Huntley answered 8/3, 2014 at 6:49 Comment(0)
F
12

For those still looking for an answer, Apple has added the searchTextField property to UISearchBar in iOS 13. searchTextField is a UISeachTextField which inherits from UITextField.

let searchBar = UISearchBar()
var searchField : UITextField
if #available(iOS 13.0, *) {
    searchField = searchBar.searchTextField
} else {
    searchField = //One of the other methods listed
}
Fanfaronade answered 19/6, 2019 at 15:54 Comment(0)
L
10

iOS 13.x & Swift 5.x:

Do the following to access the UITextField in UISearchBar.

extension UISearchBar {

    /// Returns the`UITextField` that is placed inside the text field.
    var textField: UITextField {
        if #available(iOS 13, *) {
            return searchTextField
        } else {
            return self.value(forKey: "_searchField") as! UITextField
        }
    }

}
Latvina answered 30/10, 2019 at 9:6 Comment(0)
I
6

Starting from IOS-5 you have the appearance proxy, see: http://developer.apple.com/library/ios/#documentation/uikit/reference/UISearchBar_Class/Reference/Reference.html (there are two sections called "Customizing Appearance", check both).

Here's a working example, it modifies all UISearchBars in the app:

[[UISearchBar appearance] setSearchFieldBackgroundImage:[UIImage imageNamed:@"text_box"] forState:UIControlStateNormal];
[[UISearchBar appearance] setImage:[UIImage imageNamed:@"search_icon"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
mysearchBar.tintColor = [UIColor whiteColor];
Ignoble answered 16/1, 2013 at 11:2 Comment(0)
T
4

Implementation Change Resistant & High Performance

To anyone reading this and wondering how the text field of a search bar can easily be accessed in Swift; you can extend UISearchBar to add a textField property by using the following piece of code which is resistant to underlying implementation changes and caches the found result so it is high performance.

import UIKit

private var foundTextFieldAssociationKey = UInt8()

extension UISearchBar {

  var textField: UITextField {
    get {
      let value = objc_getAssociatedObject(self, &foundTextFieldAssociationKey) as? UITextField

      if value == nil {
        let findInView = (UIView) -> UITextField? = { view in
          for subview in view.subviews {
            if let textField = (subview as? UITextField) ?? findInView(subview) {
              return textField
            }
          }
          return nil
        }

        guard let foundTextField = findInView(self) else {
          fatalError("UISearchBar doesn't seem to have a UITextField anywhere in the view hierarchy")
        }

        textField = foundTextField
        return foundTextField
      }

      return value!
    }
    set {
      objc_setAssociatedObject(self, &foundTextFieldAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_ASSIGN)
    }
  }

}

If you wish to change the name of the property, make sure you don't change it to searchField. That will mess your search bar up.

Tehuantepec answered 1/4, 2015 at 23:52 Comment(4)
How about having just return self.valueForKey("_searchField") as? UITextField?Gotcher
@Gotcher That works. I doubt Apple will change the key sometime soon but when using hacky solutions I personally prefer to find a way to do it that is a bit resilient to underlying implementation changes.Tehuantepec
@abishek-bedi I edited your changes back. My code was old but you edited the core of the implementation and changed it to something else entirely. The heart of my implementation lies in not relying on _searchField in order to be resistant to core implementation changes.Tehuantepec
Hey Great Solution there. Apple has caught this private API with new IDEEffortful
L
3

Now in iOS 13 you have searchTextField property to directly access the text field.

Latish answered 27/9, 2019 at 14:40 Comment(0)
T
2

I have found for iOS 10 I need to do this (borrowed from above and adapted quickly)

extension UISearchBar {
    var textField: UITextField? {

    func findInView(_ view: UIView) -> UITextField? {
        for subview in view.subviews {
            print("checking \(subview)")
            if let textField = subview as? UITextField {
                return textField
            }
            else if let v = findInView(subview) {
                return v
            }
        }
        return nil
      }

      return findInView(self)
    }
 }  
Topology answered 22/12, 2016 at 19:18 Comment(0)
T
2

Short and Simple

extension UISearchBar {
    var textField:UITextField {
        guard let txtField = self.value(forKey: "_searchField") as? UITextField else {
            assertionFailure()
            return UITextField()
        }
        return txtField
    }
}
Titanite answered 7/9, 2017 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.