Make UISearchBar background clear - ios

I am not able to clear search bar I have tried to make it clear by setting its background color clear and I have also placed one image under searchbar
I have also made clear background of searchbar
for (UIView *subview in self.searchBarHome.subviews) {
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[subview removeFromSuperview];//please help me to make clear background of uisearchbar
break;
}
}
[self.searchBarHome setBackgroundColor:[UIColor clearColor]];

For iOS7+, all you need to do is:
[self.searchBarHome setBackgroundColor:[UIColor clearColor]];
[self.searchBarHome setBarTintColor:[UIColor clearColor]]; //this is what you want
NOTE: This will not work for iOS6
For iOS6+, the following will take care of it even in iOS7:
[self.searchBarHome setBackgroundColor:[UIColor clearColor]];
[self.searchBarHome setBackgroundImage:[UIImage new]];
[self.searchBarHome setTranslucent:YES];

Here's my solution in Swift 3 (a combo of Scarafone's and Andrew2M's answers):
for view in searchBar.subviews.last!.subviews {
if type(of: view) == NSClassFromString("UISearchBarBackground"){
view.alpha = 0.0
}
}
or alternatively:
searchBar.barTintColor = UIColor.clear
searchBar.backgroundColor = UIColor.clear
searchBar.isTranslucent = true
searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)

UISearchBar includes two subviews,they are 'UISearchBarBackground' and 'UITextField'. In IOS8, you need to remove 'UISearchBarBackground' to clear it.
for (UIView *subview in [[yourSearchBar.subviews lastObject] subviews]) {
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[subview removeFromSuperview];
break;
}
}

Removing the UISearchBarBackground may result in unknown behavior particularly if as you begin to use the element in more advanced ways.
Ruozi's answer was my preferred solution for grabbing the UISearchBarBackground element however I would suggest setting the alpha to 0 rather than removing the view with the following:
for (UIView *subview in [[self.searchBar.subviews lastObject] subviews]) {
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
[subview setAlpha:0.0];
break;
}
}
Add the above code to your UIViewController subclass that contains an IBOutlet *searchBar. This code snippet will acheive a transparent background for both iOS8 and iOS9.
In addition it may be better design decision to include this code in your UISearchBar subclass in order to avoid cluttering your viewController.

For anyone trying to find a non hacky solution to this, just set the background image to nil on your Storyboard/Xib file. Literally, simply write nil in the background image field of the UISearchBar.

If you want to change this...
To this...
Use:
self.searchBar.searchTextField.backgroundColor = .clear

Simply use searchBar.searchBarStyle = .minimal works for me.
I had used many workarounds for a long time, until i discover this property accidentally, and works like a charm.

For anyone coming here and not being able to make the remove or alpha solution work for you, make sure you have your searchBar SearchStyle NOT on MINIMALIST. Change it to Default and use any of the codes provided here

For iOS 13+ we can simply use:
searchBar.searchTextField.backgroundColor = .clear
but other solutions like:
searchBar.setSearchFieldBackgroundImage(UIImage(), for: .normal)
searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)
creates a background on the searchBar which hides the placeholder and doesn't allow to interact with the searchBar. The solution for iOS 12 and below is to use an approach similar to #Get Schwifty.

Setting the backgroundColor and barTintColor did not work me iOS 9+, left me with a black background. However Ruozi solution will work. Here is a swift version of the same code.
for view in _searchBar.subviews.last!.subviews {
if view.isKindOfClass(NSClassFromString("UISearchBarBackground")!) {
view.removeFromSuperview()
}
}

My solution working on Swift 4.1 | iOS 11.4 where I change the background and text colors of UISearchBar
The key is to find the UISearchBar's UITextField component and to change its parameters:
let searchTextField = searchBar.value(forKey: "searchField") as? UITextField
searchTextField?.textColor = UIColor.white
searchTextField?.backgroundColor = UIColor.red
searchTextField?.attributedPlaceholder = NSAttributedString(string: "Your Placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white.withAlphaComponent(0.5)])
Then I set the "search" and the "clear" image
//search image
searchBar.setImage(UIImage(named: "icon_search"), for: UISearchBarIcon.search, state: .normal)
//clear image
searchBar.setImage(UIImage(named: "icon_search_clear"), for: UISearchBarIcon.clear, state: .normal)

extension UISearchBar {
func changeSearchBarColor(fieldColor: UIColor, backColor: UIColor, borderColor: UIColor?) {
UIGraphicsBeginImageContext(bounds.size)
backColor.setFill()
UIBezierPath(rect: bounds).fill()
setBackgroundImage(UIGraphicsGetImageFromCurrentImageContext()!, for: UIBarPosition.any, barMetrics: .default)
let newBounds = bounds.insetBy(dx: 0, dy: 8)
fieldColor.setFill()
let path = UIBezierPath(roundedRect: newBounds, cornerRadius: newBounds.height / 2)
if let borderColor = borderColor {
borderColor.setStroke()
path.lineWidth = 1 / UIScreen.main.scale
path.stroke()
}
path.fill()
setSearchFieldBackgroundImage(UIGraphicsGetImageFromCurrentImageContext()!, for: UIControlState.normal)
UIGraphicsEndImageContext()
}
}

Subclass the uisearchbar and override initWithFrame and initWithCoder method and set the background color as
// For searchbar created programmatically
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self configureSetup];
}
return self;
}
// For search bar created on xib
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self configureSetup];
}
return self;
}
- (void)configureSetup
{
self.backgroundColor = [UIColor clearColor];
}
and use the subclassed searchbar instead in place where you specified UISearchBar

Oh man! I've been looking everywhere for a solution and trying multiple things. As #gmogames had mentoned above you can use any of these answers, but make sure the Search Bar Style is set to default or it won't work. So, to clarify on the solution this is what worked for me:
Set Search Bar Style to default in the Storyboard or code(wherever you created the UISearchBar.
Then add this code to your view controller:
mySearchBar.searchTextField.backgroundColor = .clear

For iOS 12, swift 4.x
A bit too hacky but Debug view hierarchy shows _UISearchBarSearchFieldBackgroundView is responsible to the background color. To get to it, ...
for subview in searchBar.subviews.last!.subviews {
if subview.isKind(of: NSClassFromString("UISearchBarTextField")!) {
for v in subview.subviews {
if v.isKind(of: NSClassFromString("_UISearchBarSearchFieldBackgroundView")!) {
v.removeFromSuperview()
}
}
}
}
This is all too hacky. I prefer asking designer to accept Apple default color.

searchBarStyle = .default
searchTextField.backgroundColor = .yourColor
With this combination, you can remove the gray background of searchTextField and set yours!

I tried #Johnson's answer however it didn't work well for me. (iOS 13, swift 5)
However the logic behind the solution seemed well. So tried to iterate all subviews of the searchBar and it worked!
I hope, it will help :)
Solution also worked for me in iOS 12.4 - swift 5
Remove Background Method
private func removeBackground(from searchBar: UISearchBar) {
guard let BackgroundType = NSClassFromString("_UISearchBarSearchFieldBackgroundView") else { return }
for v in searchBar.allSubViewsOf(type: UIView.self) where v.isKind(of: BackgroundType){
v.removeFromSuperview()
}
}
Helper Methods -> UIViewExtension
extension UIView {
public func allSubViewsOf<T : UIView>(type : T.Type) -> [T]{
var all = [T]()
func getSubview(view: UIView) {
if let wrapped = view as? T, wrapped != self{
all.append(wrapped)
}
guard view.subviews.count>0 else { return }
view.subviews.forEach{ getSubview(view: $0) }
}
getSubview(view: self)
return all
}
}

Swift 5.4, iOS 14.5.
Here is the default UISearchBar, on top of a white background:
And the same setup on top of a grey background:
To make the background of the search bar clear, set the search bar style to minimal. This removes the search bar's background and makes the search field translucent.
searchBar.searchBarStyle = .minimal
Then, set the search text field's background color to whatever you want. In this case, I've set it to white.
searchBar.searchTextField.backgroundColor = .white
You can see the result of this here:
If you set searchBar.searchTextField.backgroundColor = .red:

Related

Unable to set correct background color to UISearchTextField

Please take a look at this code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.obscuresBackgroundDuringPresentation = NO;
self.navigationItem.searchController = self.searchController;
self.definesPresentationContext = YES;
self.searchController.searchBar.placeholder = NSLocalizedString(#"Search", #"search placeholder");
self.searchController.searchBar.searchTextField.backgroundColor = [UIColor redColor];
}
Looks pretty simple. I'm trying to set red background color to UISearchTextField. But unfortunately the result color is not precisely red. When I check the color with ColorSync utility it shows RGB as 0.9255, 0.0, 0.0667 which is not what I need. Of course red is just a simplified example. It applies to any color. Actually I need to set a color with precise RGB and unable to do so. Obviously iOS applies some tint to the search bar somehow. What I tried was: applying clear color as tint to the search bar and text field along with setting background image but all in vain. This little tint never goes away. Any ideas, guys? How do I set a precise color?
Here is the solution it will help you
import UIKit
extension UISearchBar {
func getTf() -> UITextField? { return value(forKey: "searchField") as? UITextField }
func setTf(color: UIColor) {
guard let tf = getTf() else { return }
switch searchBarStyle {
case .minimal:
tf.layer.backgroundColor = color.cgColor
tf.layer.cornerRadius = 2
case .prominent:
break,
default:
tf.backgroundColor = color
#unknown
default: break
}
}
}
For Usage
searchBar.searchBarStyle = .minimal

How to change text color of PlaceHolder in UISearchBar? (iOS 13)

After looking for updated (iOS 13) answers, I didn't find any solutions to this simple problem : How to change the textColor of the placeholder in an UISearchBar ?
My app doesn't handle Light/Dark mode. I don't want the system to change my UIPlaceHolder text color. I want it to be always white.
if #available(iOS 13.0, *) {
let attrString = NSMutableAttributedString(string: "My PlaceHolder")
attrString.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], range: NSRange(location: 0, length: attrString.length))
searchController.searchBar.searchTextField.attributedPlaceholder = attrString
}
I expected this code to work. I thought the new property searchTextField would have made it easier to customize my UISearchBar.
EDIT:
This code kind of works in the viewDidAppear method :
if #available(iOS 13.0, *) {
searchController.searchBar.searchTextField.attributedPlaceholder = NSAttributedString(string: "My PlaceHolder", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white.withAlphaComponent(0.80)])
}
The issue is that the color is changing when you scroll up and down.
As you already mentioned, your code works only in viewDidAppear, which makes the placeholder to flicker from the default gray color to the preferred color.
However, there seem to be a time before viewDidAppear (I couldn't figure it out when exactly), to change the placeholder before the view actually appears.
I suppose, this may be connected to how iOS handles light/dark mode and/or an iOS bug.
The solution I came out with that works around the issue:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 13.0, *) {
let placeholder = NSAttributedString(string: "Search",
attributes: [
.foregroundColor: UIColor.white
])
let searchTextField = searchBar.searchTextField
// Key workaround to be able to set attributedPlaceholder
DispatchQueue.global().async {
DispatchQueue.main.async {
searchTextField.attributedPlaceholder = placeholder
}
}
}
}
There seem to be no performance and/or other downside to this method.
If anybody else comes with a better approach, feel free to collaborate.
you can set this with UITextField appearance property. check this line of code
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
I guess the reason why it doesn't work is probably the searchController.searchBar.searchTextField = nil you got.
searchTextField is a new property for iOS 13, which can be done if you only support >= iOS 13. If you want to adapt to the previous version of iOS 13, you can traverse UISearchBar to find UISearchBarTextField and directly set the found UISearchBarTextField.
The code I looked up is probably like this, I put it in the Category of UIView.
- (UIView *)findChildViewClass:(Class)childViewClass fromView:(UIView *)fromView{
for (UIView *subView in fromView.subviews) {
if ([subView isMemberOfClass:childViewClass]) {
return subView;
}
UIView *finalView = [self findChildViewClass:childViewClass fromView:subView];
if (finalView) {
return finalView;
}else{
continue;
}
}
return nil;
}
When used, you can customize a searchTextField property to inherit from UITextField to save the found value.
_searchTextField = (UITextField *)[searchBar findChildViewClass:NSClassFromString(#"UISearchBarTextField") fromView: searchBar];
This is what I use now, it is working, I hope to be useful to you.

How to clear UISearchBar background color in iOS10 Swift?

There are older version of this question for older versions of iOS no longer works due to the layout changes in UISearchBar.
I've tried the following to completely remove the background color of UISearchBar but it doesn't work. (I tried to look up the hierarchy views of it but xCode kept crashing for this option.)
private func clearBackgroundColor() {
for view in self.subviews {
view.backgroundColor = UIColor.clear
for subview in view.subviews {
subview.backgroundColor = UIColor.clear
}
}
}
Any ideas or suggestions?
Thanks!!
private func clearBackgroundColor() {
guard let UISearchBarBackground: AnyClass = NSClassFromString("UISearchBarBackground") else { return }
for view in self.subviews {
for subview in view.subviews where subview.isKind(of: UISearchBarBackground) {
subview.alpha = 0
}
}
}
This is what I did in the end that worked. Thanks all for your answers.
I think you are mention about BarTintColor of search bar
try this:
searchBar.barTintColor = .white
Just set the Search Bar style to .Minimal in Interface Builder or code and the background will go transparent.
Try this.
class CustomSearchBar: UISearchBar {
override func layoutSubviews() {
super.layoutSubviews()
clearBackgroundColor() // function in the question
}
}
private func clearBackgroundColor() {
for view in self.subviews {
view.backgroundColor = UIColor.clear
for subview in view.subviews {
subview.backgroundColor = UIColor.clear
}
}
}
try set backgroundimage:
[searchBar setBackgroundImage:[UIImage new]];
let searchBar = UISearchBar()
searchBar.backgroundImage = UIImage()
You can change search style to "Minimal" in Interface Builder

How can I set the tint color of a MPVolumeView?

How can I set the tint color of a MPVolumeView?
I see the method:
setMinimumTrackTintColor:
and the property
minimumTrackTintColor
however using either of those throws an exception.
I was told I need to call
setMinimumTintColor
or set the property
minimumTrackTintColor
on the underlying UISlider, however I don't know how to do that.
Thanks!
In iOS 7 you simply can change the slider color of a MPVolumeView like this:
CGRect rect1 = CGRectMake(17, 45, 220, 0);
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:rect1];
volumeView.tintColor = [UIColor colorWithRed:0.0f/255.0f green:255.0f/255.0f blue:127.0f/255.0f alpha:1.0f];
Hope this helps.
I have searched for answer to this for a very long time, because in my app I need to set volumeView colors dynamically. Since UISlider provides a way to change its tint color, you can cycle through MPVolumeView subviews until you find an instance of UISlider class and then operate on this one.
Here is the code in Swift:
func customSlider() {
let temp = mpVolView.subviews
for current in temp {
if current.isKind(of: UISlider.self) {
let tempSlider = current as! UISlider
tempSlider.minimumTrackTintColor = .yellow
tempSlider.maximumTrackTintColor = .blue
}
}
}
Result:
This worked for me to change the route button color too:
volumeView.tintColor = .green
if let routeButton = volumeView.subviews.compactMap({ $0 as? UIButton }).first,
let image = routeButton.image(for: .normal) {
routeButton.setImage(image.withRenderingMode(.alwaysTemplate), for: [])
}

Hide UISearchBar clear text button

I would like to know how to hide or not display the UISearchBar cross that appears in the textField fo the UISearchBar
I have tried using this
filterSearchBar.showsCancelButton = NO;
However this is an actual cancel button not the small grey cross, so I would like to know if there is an equivalent for the small grey button that shows in the UISearchBar.
You need to get the textField of the Search Bar:
UITextField *textField = [searchBar valueForKey:#"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;
hope this help! =)
There's a better way to do this, and you don't have to use private APIs or traverse subviews to do it, so this solution is App Store safe.
UISearchBar has a built-in API for doing this:
[UISearchBar setImage:forSearchBarIcon:state]
The SearchBar icon key you want is UISearchBarIconClear, and you want the UIControlStateNormal state. Then give it a clear image for the image, and you're done.
So, it should look like this:
[searchBar setImage:clearImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];
Swift 4
Adding to Alexander's answer and block user interaction on clear button:
To hide button:
searchBar.setImage(UIImage(), for: .clear, state: .normal)
To disable user interaction on the clear button, simply subclass UISearchBar
class CustomSearchBar: UISearchBar {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
if view is UIButton {
return view?.superview // this will pass-through all touches that would've been sent to the button
}
return view
}
}
Based on #Gines answer, here is the Swift version:
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
    guard let firstSubview = searchBar.subviews.first else { return }
    firstSubview.subviews.forEach {
     ($0 as? UITextField)?.clearButtonMode = .never
    }
}
Swift 5
Tested on iOS 13
One liner working for me:
searchBar.searchTextField.clearButtonMode = .never
You can also set it to .whileEditing to have it displayed when the user is typing and then removed when the search bar loses focus.
Swift 3, based on #Alexsander answer:
searchBar.setImage(UIImage(), for: .clear, state: .normal)
You can remove the clear text button for all UISearchBar instances:
[UITextField appearanceWhenContainedInInstancesOfClasses:#[[UISearchBar class]]].clearButtonMode = UITextFieldViewModeNever;
Swift 5
Just add a single line below
searchBar.searchTextField.clearButtonMode = .never
Swift 3 solution :
extension UISearchBar{
var textField : UITextField{
return self.value(forKey: "_searchField") as! UITextField
}
}
Usage :
searchBar.textField.clearButtonMode = .never
I tried different solutions about this issue, even the one selected in this post, but they didn't work.
This is the way I found to solve this issue:
UIView *subview = [[searchBar subviews] firstObject]; //SearchBar only have one subview (UIView)
//There are three sub subviews (UISearchBarBackground, UINavigationButton, UISearchBarTextField)
for (UIView *subsubview in subview.subviews)
{
//The UISearchBarTextField class is a UITextField. We can't use UISearchBarTextField directly here.
if ([subsubview isKindOfClass: [UITextField class]])
{
[(UITextField *)subsubview setClearButtonMode:UITextFieldViewModeNever];
}
}
Try this:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
UITextField *textField = [searchBar valueForKey:#"_searchField"];
textField.clearButtonMode = UITextFieldViewModeNever;
}
In Case of Swift 2.3 just use :
var searchBar = UISearchBar();
searchBar.frame = CGRectMake(0, 0, 00, 20))
for subview: UIView in (searchBar.subviews.first?.subviews)!
{
if (subview.isKindOfClass(UITextField) )
{
let textFieldObject = (subview as! UITextField)
textFieldObject.clearButtonMode = .Never;
}
}
Swift 2.3, based on #Alexsander answer:
searchBar.setImage(UIImage(named: "SearchClearIcon"), forSearchBarIcon: UISearchBarIcon.Clear, state: UIControlState.Highlighted)
searchBar.setImage(UIImage(named: "SearchClearIcon"), forSearchBarIcon: UISearchBarIcon.Clear, state: UIControlState.Normal)
Converting Soto_iGhost's answer to Swift 4:
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
let textField: UITextField = searchBar.value(forKey: "_searchField") as! UITextField
textField.clearButtonMode = .never
}
If you have an outlet of UISearchBar the you can write above code anywhere in your class.
thijsonline's answer in swift:
(UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self])).clearButtonMode = .never

Resources