Setting UISearchBar's search field background image changes the padding

6.6k views Asked by At

When I set a search field background image on a UIImage, the padding between the magnifying glass and placeholder text in the search bar when selected changes.

With the default background:

Good padding

With a custom background:

Bad padding

This change is caused by these two lines:

UIImage *colorImage = [UIImage imageWithColor:[UIColor grayColor] size:CGSizeMake(28, 28)];
[self setSearchFieldBackgroundImage:[colorImage imageWithRoundedCorners:5] forState:UIControlStateNormal];

imageWithRoundedCorners: is a category method that simply draws the image onto a CALayer with a corner radius and then creates a UIImage from the graphics context.

Why is this and how can I avoid this? I tried passing an explicitly resizable image, but that had no effect.

3

There are 3 answers

2
Ryan Poolos On BEST ANSWER

Its odd that it resets it, however you can use something like this to set it to your liking after setting the background image. searchTextPositionAdjustment is a property on UISearchBar and works perfectly. 8.0 seems to be the default, but you could set it to whatever you like.

[self.searchBar setSearchFieldBackgroundImage:[self imageWithColor:[UIColor grayColor] andSize:CGSizeMake(28.0, 28.0)] forState:UIControlStateNormal];
[self.searchBar setSearchTextPositionAdjustment:UIOffsetMake(8.0, 0.0)];

enter image description here

0
Edouard Barbier On

Updated solution for Swift 4

searchTextPositionAdjustment = UIOffset(horizontal: 8.0, vertical: 0.0)
0
Ben On

For all those now using Swift, you can use the following code (works in Swift 2)

let searchBarBackground = UIImage.roundedImage(UIImage.imageWithColor(UIColor.whiteColor(), size: CGSize(width: 28, height: 28)),cornerRadius: 2)
searchBar.setSearchFieldBackgroundImage(searchBarBackground, forState: .Normal)
searchBar.searchTextPositionAdjustment = UIOffsetMake(8.0, 0.0)

Use this with an extension to UIImage:

extension UIImage {
     class func imageWithColor(color: UIColor, size: CGSize) -> UIImage {
        let rect: CGRect = CGRectMake(0, 0, size.width, size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
    class func roundedImage(image: UIImage, cornerRadius: Int) -> UIImage {
        let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: image.size)
        UIGraphicsBeginImageContextWithOptions(image.size, false, 1)
        UIBezierPath(
            roundedRect: rect,
            cornerRadius: CGFloat(cornerRadius)
        ).addClip()
        image.drawInRect(rect)
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

To give something looking like this:

enter image description here