iOS 11 UISearchBar background color - ios

I understand that this question has been asked many, many times on SO. However, as Apple does best, with the release of iOS 11, they seem to have made a seemingly unnecessary change to the UISearchBar, specifically it's view hierarchy.
In further, the "text field" of a search bar is no longer accessible in the search bar's subviews, causing all of the previous solutions to "access" and change the background color of the text field, or any property of the text field for that matter.
Does anyone know how to actually adjust the background color of a search bar in iOS 11?
FYI:
I am specifically talking about the color behind the text... which now as of 11 defaults to white unless you specify the search bar style to be minimal.
UPDATE 1:
Since my posting of this question, I still have not found a valid or really any real solution to this issue. The closest I have seem to come is to dive deep into the appearance for instance properties
[[UISearchBar class] appearanceWhenContainedInInstancesOfClasses:(nonnull NSArray<Class<UIAppearanceContainer>> *)]
of the UISearchBar. Playing around with the found UITextField via methods such as the following:
if ([view isKindOfClass:[UITextField class]]) {
return (UITextField*)view;
}
UITextField *searchTextField;
for (UIView *subview in view.subviews) {
searchTextField = [self searchViewForTextFieldBg:subview];
if (searchTextField) {
break;
}
}
return searchTextField;
you can begin drawing a new background view to be placed behind the view. However, the issues I had found too tedious to pursue further were drawing the a view with the correct frame / bounds to mimic exactly the original background.
Hopefully someone can find the actual solution to this problem. Nice miss apple...

I think you may be looking for this, right? But I've it in Swift :(
#IBOutlet weak var sbSearchBar: UISearchBar!
if let textfield = sbSearchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
textfield.backgroundColor = UIColor.yellow
}
Here is result:

This Swift code changes the background color of the text field:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// background color of text field
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = .cyan
}
This is the result

let searchBar = UISearchBar(frame: CGRect())
let searchField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField
let searchBarBackground: UIView? = searchBar.value(forKey: "background") as? UIView
// searchBarBackground?.removeFromSuperview()
if searchField != nil {
var frame = searchField?.frame
frame?.size.height = 30
searchField?.frame = frame!
searchField?.backgroundColor = .yellow
}
searchBar.barTintColor = .red
searchBar.delegate = self
searchBar.backgroundColor = .green
Runtime Views Hierarchy
If we set background colors for UISearchBar with code above, we'll see the colored subviews as follow images(click links to see).

backgroundColor for Superview of UISearchBar subviews
We can see the Class Name of green view is UISearchBar in Object inspector.
So, if we use searchBar.backgroundColor = .green, we'll set the backgroundColor of Superview green. Therefore, the UISearchBar instance property backgroundColor will set the superview's background color.
Superview of UISearchBar
barTintColor for UISearchBarBackground
We can see the Class Name of red view is UISearchBarBackground in Object inspector.
However, there's no direct method to access the view, we can use KVC searchBar.value(forKey: "background") as? UIView try to get searchBarBackground.
If we use searchBar.barTintColor = .red, we'll set the backgroundColor of UISearchBarBackground's view red. In order to remove two black border on the tint bar layer, we have to remove the background from superview.
barTintColor of UISearchBar
searchField?.backgroundColor for UITextField
We can see the Class Name of yellow view is _UISearchBarSearchFieldBackgroundView (Subview of UISearchBarTextField) in Object inspector.
There's no direct method to access the searchField, same as searchBarBackground. We can also use KVC searchField: UITextField? = searchBar.value(forKey: "searchField") as? UITextField try to get searchField.
If we use searchField?.backgroundColor = .yellow, we'll set the backgroundColor of UITextField yellow. Therefore, if we want to set text field background color, we have to access the searchField with KVC first
UITextField of UISearchBar

It's much simpler than that in Swift 5.
searchBar.barTintColor = .black
searchBar.searchTextField.backgroundColor = .white

Swift 4-5
searchController.searchBar.barTintColor = .white

Related

How can i change the color of placeholder in SearchBar in Swift Xcode

I have this design of the search bar and the output is not the same.
I have tried TintColor, BackgroundColor, Different Styles in addition to many extensions on the internet and yet i still cannot achieve it.
All what i have so far is the normal searchbar with the grey area color at the placeholder.
To change the textColor for placeholder in SearchBar you need to extract the searchField from searchBar and then placeholderLabel from searchField. Here's how:
let searchField = searchBar.value(forKey: "searchField") as? UITextField
searchField?.textColor = myColor
let placeholderLabel = searchField?.value(forKey: "placeholderLabel") as? UILabel
placeholderLabel?.textColor = myColor

Remove border between View and Search Bar

So in Xcode I'm trying to create a seamless search bar. So I'm trying to replicate something like this
Note how the status bar is the same color as the search bar. Now here's the result to my approach.
What I did was add a View to cover up the default status bar with the blue background. Then I added a search bar and changed it's background to blue. For some reason I end up getting a black border between the two, which ruins the "seamless" design. Any ideas on how I can remove the black border in Swift?
For iOS 7+:
searchBar.backgroundImage = UIImage()
Otherwise this will work on all iOS versions:
searchBar.layer.borderWidth = 1
searchBar.layer.borderColor = thatBlueColor.CGColor
Swift 4
searchBar.barTintColor = UIColor.white
searchBar.setBackgroundImage(UIImage.init(), for: UIBarPosition.any, barMetrics: UIBarMetrics.default)
Sample image
Upate Sample code for navigation bar and search bar background color:
Navigation bar color
self.navigationController?.navigationBar.barTintColor = .blue
Search bar color
searchBarProperty.backgroundColor = self.navigationController?.navigationBar.barTintColor
Note : Navigation bar and search bar color must be same.
Sample image with blue navigation bar and blue search bar
In Xcode 8.3 and Swift 3
Create an outlet from your search bar to your ViewController (I called mine searchBarOutlet for this example).
Below viewDidLoad insert the following.
self.searchBarOutlet.backgroundImage = UIImage()
You should have the following:
override func viewDidLoad() {
super.viewDidLoad()
self.searchBarOutlet.backgroundImage = UIImage()
When you run your app the lines will be gone (they will still be visible on storyboard).
In my case, beyond the edge of search bar needed to take the edge off also the navigation bar.
C# code:
NavigationController.NavigationBar.ShadowImage = new UIImage();
NavigationController.NavigationBar.SetBackgroundImage (new UIImage (), UIBarMetrics.Default);
Swift code:
self.navigationController.navigationBar.shadowImage = UIImage()
self.navigationController.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
The best solution to remove top and bottom default borders is:
To set a new empty searchBar background layout in viewDidLoad for example:
searchBar.backgroundImage = UIImage()
I found these answers to be more complicated than they needed to be. You can just modify the constraint that is binding the searchBar view and the other view to -1pts so that it overlaps exactly by the height of the searchBar's margin.
I encountered the same situation when I set the statusBar and searchBar translucent.
In this situation, I couldn't resolve with the answers written here however I could solve by the following approach.
put UIVisualEffectView on self.view (view of your VC)
make custom class of searchBar, which background is transparent
(also let statusBar transparent)
(swift4 code)
class TransparentSearchBar: UISearchBar {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
makeTransparentBackground()
}
private func makeTransparentBackground() {
for view in self.subviews {
view.backgroundColor = UIColor.clear
for subview in view.subviews {
if let imageview = subview as? UIImageView {
imageview.image = nil
}
}
}
}
}
somewhere in viewDidLoad (statusBar)
let statusWindow = UIApplication.shared.value(forKey:"statusBarWindow") as! UIView
let statusBar = statusWindow.subviews[0] as UIView
statusBar.backgroundColor = UIColor.clear
in Xcode 13
select the search bar and change the search Style to Minimal

UISearchBar custom corners

I'm trying to create a search bar like this:
But I'm noticing that I'm probably going to have to replace the search bar with my own image because the search bar corners comes out wrong when I set:
self.searchController.searchBar.layer.cornerRadius = 50 // I've tried other numbers besides this too with no luck
self.searchController.searchBar.clipsToBounds = true
If I set this:
self.searchController.searchBar.layer.cornerRadius = self.searchController.searchBar.bounds.height/2
The search bar comes out like this:
Which still isn't exact like in the image.
Is there a way to replace the left and right side of the textfield with an image that way I can use the rounded corners from my custom search bar?
I am using this code UISearchBar but you can use this code with UISearchController.
let searchBar = UISearchBar()
searchBar.sizeToFit()
searchBar.placeholder = "Search"
navigationItem.titleView = searchBar
if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 14;
backgroundview.clipsToBounds = true;
}
}
You should change the radius of searchTextField inside UISearchBar .
you can do that like this :
searchBar.searchTextField.layer.cornerRadius = 20
searchBar.searchTextField.layer.masksToBounds = true
* searchBar is an outlet of UISearchBar from storyBoard
The issue here is you are setting the corner radius on the UISearchBar, not the UITextField inside it. You can do some sort of hack to get the UITextField, but that's not really recommended.
As you mentioned in your question, you'll need to use custom images and the methods shown here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISearchBar_Class/#//apple_ref/doc/uid/TP40007529-CH3-SW40
This IS working for me in swift 3 iOS 10:
searchController.searchBar.layer.cornerRadius = 20
searchController.searchBar.clipsToBounds = true
ez way for searchbarview
for subview & POPUPs [Swift 5]
override func layoutSublayers(of layer: CALayer) {
searchBarPopup.clipsToBounds = true
searchBarPopup.layer.cornerRadius = 10
searchBarPopup.layer.maskedCorners = [ .layerMaxXMinYCorner, .layerMinXMinYCorner]
}

How to remove the outer border of UITextField presented in UIAlertActionController

I am adding multiple UITextFields to my alert controller, and I don't want that ugly black box around them. I know it's not the border property of the textField, because I have tried setting that and that influences the actual textField, not the box.
I have tried
textField.superview?.backgroundColor = UIColor.redColor()
textField.superview?.layer.borderColor = UIColor.redColor().CGColor
Setting the background Color works as expected, filling in the space between the textfield and the "black border" but setting the borderColor or borderWidth on superview.layer do nothing. Any ideas?
I ended up subclassing UIAlertController.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for field in textFields! as [UITextField] {
field.superview?.superview?.layer.borderWidth = 2
field.superview?.superview?.layer.borderColor = UIColor.whiteColor().CGColor
}
}

Getting the UIKeyboard background color programmatically

Is there any way to get the UIKeyboard background color? I am putting an accessory view on top of my UIKeyboard and is trying to match its color with the keyboard background color. But, it seems, different types of keyboard has different background colors. Please see below screenshots for default and email keyboard.
Is there any way, we can find out the background color of the keyboard programmatically so that the color of the accessoryView could be changed.
Swift 5
You can use an input view and it matches the keyboard style.
let textView = UITextView()
let frame = CGRect(x: 0, y: 0, width: 0, height: 40)
textView.inputAccessoryView = UIInputView(frame: frame, inputViewStyle: .keyboard)
You could do something like this:
UIKeyboardAppearance currentAppearance = yourTextView.keyboardAppearance;
if (currentAppearance == UIKeyboardAppearanceDark) {
// dark
}
else if (currentAppearance == UIKeyboardAppearanceDefault) {
// default
}
else if (currentAppearance == UIKeyboardAppearanceLight) {
// light
}
I suggest you to get your keyboard color's RGB from DigitalColor Meter as we use this tool in Mac or you can get it by any other tool.
And then simply assign these RGB value to your accessory view and match its color with your keyboard.
The RGB value of your keyboard is seems to me is like (63,63,63) and you can use this:
[UIColor colorWithRed:63/255.0 green:63/255.0 blue:63/255.0 alpha:1]
Hopefully it will helps you.
If you're developing a custom keyboard and trying to match the background of your keyboard's view, use this in your keyboard's view controller where you set up the view:
keyboardView.backgroundColor = view.backgroundColor
My viewDidLoad() in my keyboard's view controller looks like:
var keyboardView: UIView!
let keyboardNib = UINib(nibName: "KeyboardView", bundle: nil)
keyboardView = keyboardNib.instantiate(withOwner: self, options: nil)
[0] as? UIView
keyboardView.frame.size = view.frame.size
keyboardView.backgroundColor = view.backgroundColor
view.addSubview(keyboardView)
For the dark background use
mytextfield.keyboardAppearance = UIKeyboardAppearanceAlert;

Resources