How to left align UISearchBar placeholder text
Asked Answered
O

10

13

This is the searchbar that the designers want me to create

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?

Opacity answered 4/12, 2013 at 19:9 Comment(2)
Not sure about the alignment of the text, but you might consider making the search icon into a custom 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
I've answered this on a different question. Happy to receive feedback on how to improve it: https://mcmap.net/q/902419/-how-to-right-align-text-of-uisearchbar-in-ios7Buddy
E
12

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.

Embracery answered 4/12, 2013 at 19:20 Comment(2)
But note that UISearchController seems to require using an actual UISearchBar, or a subclass.Grapery
But I want all the other built-in functionality of the search bar (cancel and x button, e.g.) - I simply want to left align the the placeholder text - is that too much to ask? And why would that be so difficult to do?Applecart
E
2

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
                }
            }
        }
    }
}
Embryonic answered 2/6, 2015 at 11:6 Comment(0)
C
2

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

Chromite answered 27/10, 2015 at 14:58 Comment(0)
E
2

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");
Euphrates answered 2/3, 2017 at 18:9 Comment(1)
my searchbar icon went out of search bar after 2-3 times resign keyboard.Voter
E
2

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

    }
Exegete answered 31/5, 2017 at 10:19 Comment(0)
E
0

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 :

  1. a background UIImageView
  2. a UITextField
  3. 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.

Exequies answered 4/12, 2013 at 19:26 Comment(1)
Thanks for the detailed answer, I will definitely be using this.Opacity
C
0

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.

Cusk answered 5/6, 2014 at 6:29 Comment(4)
if anyone down-vote any answer. first submit a correct answer.Cusk
This works flawless only if you check the how many spaces you need and add dynamically. - overriding the placeholder var, and check the size of the text agains the size of the controller, than the size of one space. If some one want me to post the code, let me know.Embryonic
Hey @DevC, I'll answer to be able to post the code, right now.Embryonic
iOS 8 will trim the whitespace around the placeholder.Applecart
R
0

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;
}
Reaper answered 6/3, 2017 at 8:53 Comment(0)
S
0

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

Sorcery answered 14/8, 2019 at 18:57 Comment(0)
O
-2

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.

Ordinarily answered 11/2, 2016 at 9:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.