How to set UiSearchBar Search icon on the right side in swift
In ViewController, leftview of searchbar textfield is the actual search icon, so make it to nil and create a image view with custom icon and set as a right view of search textfield.
Objective C
@interface FirstViewController ()
{
UISearchBar *searchBar;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
searchBar = [[UISearchBar alloc] init];
searchBar.frame = CGRectMake(15, 100, 350,50);
[self.view addSubview:searchBar];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UITextField *searchTextField = [((UITextField *)[searchBar.subviews objectAtIndex:0]).subviews lastObject];
searchTextField.layer.cornerRadius = 15.0f;
searchTextField.textAlignment = NSTextAlignmentLeft;
UIImage *image = [UIImage imageNamed:@"search"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
searchTextField.leftView = nil;
searchTextField.placeholder = @"Search";
searchTextField.rightView = imageView;
searchTextField.rightViewMode = UITextFieldViewModeAlways;
}
Swift
private var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
searchBar = UISearchBar()
searchBar.frame = CGRect(x: 15, y: 100, width: 350, height: 50)
self.view.addSubview(searchBar)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let searchTextField:UITextField = searchBar.subviews[0].subviews.last as! UITextField
searchTextField.layer.cornerRadius = 15
searchTextField.textAlignment = NSTextAlignment.left
let image:UIImage = UIImage(named: "search")!
let imageView:UIImageView = UIImageView.init(image: image)
searchTextField.leftView = nil
searchTextField.placeholder = "Search"
searchTextField.rightView = imageView
searchTextField.rightViewMode = UITextFieldViewMode.always
}
I suggest you to check Apple documentation layoutIfNeeded()
and layoutSubviews() . You'll have better understanding after reading them. The magic happens when you write searchBar.layoutIfNeeded()
instance method. Another solution is searchBar.layoutSubviews()
but Apple documentation says:
You should not call this method directly. If you want to force a layout update, call the setNeedsLayout() method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded() method.
According to @Jeyamahesan's answer. When you modify the code like below you do not need to separate the code in viewDidLoad() and ViewDidAppear().
Example:
import UIKit
class MainController: UIViewController {
private var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
searchBar = UISearchBar()
searchBar.frame = CGRect(x: 15, y: 100, width: 350, height: 50)
searchBar.layoutIfNeeded()
self.view.addSubview(searchBar)
let searchTextField:UITextField = searchBar.subviews[0].subviews.last as! UITextField
searchTextField.layer.cornerRadius = 15
searchTextField.textAlignment = NSTextAlignment.left
let image:UIImage = UIImage(named: "Search")!
let imageView:UIImageView = UIImageView.init(image: image)
searchTextField.leftView = nil
searchTextField.placeholder = "Search"
searchTextField.rightView = imageView
searchTextField.rightViewMode = UITextFieldViewMode.always
}
}
My approach to solve the issue:
MainView.swift
import UIKit
class MainView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func setupUI() {
backgroundColor = UIColor.lightGray
setupSubViews()
setupAutoLayout()
}
// MARK: Initialize UI Elements
private let searchBar: UISearchBar = {
let searchBar = UISearchBar()
searchBar.isTranslucent = false
searchBar.barTintColor = ColorPalette.LuminousDay.white
searchBar.layoutIfNeeded()
return searchBar
}()
private let searchImageView: UIImageView = {
let image = UIImage(named: "Search")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
return imageView
}()
private lazy var searchBarTextField: UITextField = { [unowned self] in
let textField = self.searchBar.value(forKey: "searchBarTextField") as! UITextField
textField.font = FontBook.SourceSansPro.Weight.semiBold.setFont(size: 24)
textField.textColor = ColorPalette.LuminousDay.charm
textField.tintColor = ColorPalette.LuminousDay.charm
textField.clearButtonMode = .never
textField.leftViewMode = .never
textField.leftView = nil
textField.rightViewMode = .always
textField.rightView = self.searchImageView
return textField
}()
private func setupSubViews() {
addSubview(searchBar)
searchBar.addSubview(searchBarTextField)
searchBarTextField.addSubview(searchImageView)
}
private func setupAutoLayout() {
searchBar.anchor(top: safeAreaLayoutGuide.topAnchor, bottom: nil,
leading: safeAreaLayoutGuide.leadingAnchor, trailing: safeAreaLayoutGuide.trailingAnchor,
centerX: nil, centerY: nil,
centerXconstant: nil, centerYconstant: nil,
size: CGSize.zero, padding: UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0))
searchImageView.setSize(size: CGSize(width: 16, height: 16))
}
}
MainController.swift
import UIKit
class MainController: UIViewController {
override func loadView() {
view = MainView()
}
override func viewDidLoad() {
super.viewDidLoad()
}
}