I need to make a custom search bar like this. Th
A working swift 3 solution for Drix answer:
import Foundation
import UIKit
class LeftAlignedSearchBar: UISearchBar, UISearchBarDelegate {
override var placeholder:String? {
didSet {
if #available(iOS 9.0, *) {
if let text = placeholder {
if text.characters.last! != " " {
// get the font attribute
let attr = UITextField.appearance(whenContainedInInstancesOf: [LeftAlignedSearchBar.self]).defaultTextAttributes
// define a max size
let maxSize = CGSize(width: UIScreen.main.bounds.size.width - 87, height: 40)
// let maxSize = CGSize(width:self.bounds.size.width - 92,height: 40)
// get the size of the text
let widthText = text.boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:attr, context:nil).size.width
// get the size of one space
let widthSpace = " ".boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:attr, context:nil).size.width
let spaces = floor((maxSize.width - widthText) / widthSpace)
// add the spaces
let newText = text + ((Array(repeating: " ", count: Int(spaces)).joined(separator: "")))
// apply the new text if nescessary
if newText != text {
placeholder = newText
}
}
}
}
}
}
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
No need to any customization just do it...
searchBar.placeholder=@"Search ";
searchbar has centeral text alignment for its place-hoder , so just give some big text. and if you text is small then just use some space after place-holder text.
A working solution for Drix answer
import Foundation
import UIKit
class LeftAlignedSearchBar: UISearchBar, UISearchBarDelegate {
override var placeholder:String? {
didSet {
if #available(iOS 9.0, *) {
if let text = placeholder {
if text.characters.last! != " " {
// get the font attribute
let attr = UITextField.appearanceWhenContainedInInstancesOfClasses([LeftAlignedSearchBar.self]).defaultTextAttributes
// define a max size
let maxSize = CGSizeMake(UIScreen.mainScreen().bounds.size.width - 87, 40)
// let maxSize = CGSizeMake(self.bounds.size.width - 92, 40)
// get the size of the text
let widthText = text.boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
// get the size of one space
let widthSpace = " ".boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
let spaces = floor((maxSize.width - widthText) / widthSpace)
// add the spaces
let newText = text + ((Array(count: Int(spaces), repeatedValue: " ").joinWithSeparator("")))
// apply the new text if nescessary
if newText != text {
placeholder = newText
}
}
}
}
}
}
}
This method appearanceWhenContainedInInstancesOfClasses is not available in iOS 8, there is a workaround for iOS 8 here
If you want your control to respond exactly how you want, you should probably make your own custom control. This control could be separated in three parts :
UIImageView
UITextField
UIButton
for the the search icon if you want the user to interact with itThe easiest way to do that is probably to create a new class MySearchBar
, with the three parts in the private interface :
@interface MySearchBar ()
@property (nonatomic, strong) UISearchBar* searchBar;
@property (nonatomic, strong) UITextField* textField;
@property (nonatomic, strong) UIButton* button;
@end
In your MySearchBar
, you can create your component, customize it, add a better look & feel. To get back the search result, your control can have a delegate id<UISearchBarDelegate>
(your UIViewController
) which will basically simulate having a standard UISearchBar.
What remains is to create your MySearchBar
in your controller and set the delegate to your view controller. The messages from the UISearchBarDelegate
can either go to your MySearchBar
to filter or do pre-treatment before sending to your UIViewController
, or go directly to your UIViewController
.