I need to make a custom search bar like this. The problem I am having is left aligning the placeholder text, as well as placing the search icon in the right. I have a png of the search icon that I have tried to use in an UIImageView
, and set that UIImageView
as the rightView
of the UISearchBar
's UITextField
. This solution has not worked, and I ran out of ideas. Does anyone have a solution?
Don't use a UISearchBar
if you need to do these kinds of customizations. You'll have to make your own using a UITextField
and a UIImageView
, and responding to the delegate calls.
Based in Mohittomar answer, as asked by @DevC to add spaces to the end of the place holder, here the code in swift:
I subclass placeholder in the UISearchBar, after set the value, I check if the last character is a space. then get the size of one space and how many spaces I need to add to align left.
class SearchBar: UISearchBar, UISearchBarDelegate {
override var placeholder:String? {
didSet {
if let text = placeholder {
if text.last != " " {
// get the font attribute
let attr = UITextField.s_appearanceWhenContainedIn(SearchBar).defaultTextAttributes
// define a max size
let maxSize = CGSizeMake(UIScreen.mainScreen().bounds.size.width - 60, 40)
// get the size of the text
var widthText = text.boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
// get the size of one space
var widthSpace = " ".boundingRectWithSize( maxSize, options: .UsesLineFragmentOrigin, attributes:attr, context:nil).size.width
let spaces = floor((maxSize.width - widthText) / widthSpace)
// add the spaces
let newText = text + (" " * spaces)
// apply the new text if nescessary
if newText != text {
placeholder = newText
}
}
}
}
}
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
SWIFT 3
swift 3 does not allow to override placeholder property. This is the modified version of Drix answer.
func setPlaceHolder(placeholder: String)-> String
{
var text = placeholder
if text.characters.last! != " " {
// define a max size
let maxSize = CGSize(width: UIScreen.main.bounds.size.width - 97, height: 40)
// let maxSize = CGSizeMake(self.bounds.size.width - 92, 40)
// get the size of the text
let widthText = text.boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:nil, context:nil).size.width
// get the size of one space
let widthSpace = " ".boundingRect( with: maxSize, options: .usesLineFragmentOrigin, attributes:nil, 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 {
return newText
}
}
return placeholder;
}
and call the function as :
searchBar.placeholder = self.setPlaceHolder(placeholder: "your placeholder text");
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
}
*/
}
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 :
- a background
UIImageView
- a
UITextField
- a
UIButton
for the the search icon if you want the user to interact with it
The 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
.
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.
Version for Xamarin
SearchBar.MovePlaceHolderLeft();
public static void MovePlaceHolderLeft(this UISearchBar searchbar)
{
NSAttributedString text = new NSAttributedString(searchbar.Placeholder ?? "");
// define a max size
var maxSize = new CGSize(width: UIScreen.MainScreen.Bounds.Size.Width - 97, height: 40);
// get the size of the text
var widthText = text.GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, null).Size.Width;
// get the size of one space
var widthSpace = new NSAttributedString(" ").GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, null).Size.Width;
var spaces = Math.Floor((maxSize.Width - widthText) / widthSpace);
// add the spaces
string newText = searchbar.Placeholder;
for (double i = 0; i < spaces; i++)
{
newText += " ";
}
searchbar.Placeholder = newText;
}
it could be done from story board there is combo box with name semantic on attribute inspector of search bar if you set it to force right to left its done you have right align search bar and it has a similar thing for aligning from left
It's too late, but if anyone is still wondering the solution, then you can follow this.
UITextField *searchTextField = [searchBarController.searchBar valueForKey:@"_searchField"];
You can get the search field using above code. Now simply use the properties you want to use, like.
searchTextField.layer.cornerRadius = 10.0f;
searchTextField.textAlignment = NSTextAlignmentLeft;
PS. Text alignment property is used for text and placeholder both. Thanks.
© 2022 - 2024 — McMap. All rights reserved.
UIButton
, placed on top of the search bar, that functions as an "Enter" button. I've encountered a few apps that do that, and I've always enjoyed having the option of not having to tap the search field, bring up the keyboard, and hit "Search" from there if I want to re-run the search. – Novikoff