Hello I'm trying to change the UISearchbar to rectangular shape rather then rounded rectangular and merge it with the navigation bar with same color.
The background color of the navigation bar should be the same as the background of the search bar but there's difference and also there's a clear edge shown both should show the background color #be1b25 and not the #bc303a. As well the textfield still showing rounded rectangle and not fully rectangle.
The Main View Controller code
#IBOutlet weak var searchBar: UISearchBar!
self.navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.backgroundColor = UIColor().HexToColor(hexString: REDCOLOR)
searchBar.backgroundColor = UIColor().HexToColor(hexString: REDCOLOR)
searchBar.tintColor = UIColor().HexToColor(hexString: REDCOLOR)
searchBar.barTintColor = UIColor().HexToColor(hexString: REDCOLOR)
searchBar.barStyle = .default
searchBar.placeholder = NetworkManager.sharedInstance.language(key: "searchentirestore")
searchBar.layer.cornerRadius = 0;
searchBar.clipsToBounds = false;
searchBar.barTintColor = UIColor().HexToColor(hexString: REDCOLOR)
searchBar.layer.borderWidth = 0
//searchBar.layer.borderColor = UIColor.clear as! CGColor
The UISearchBar Extension
extension UISearchBar {
private var textField: UITextField? {
return subviews.first?.subviews.flatMap { $0 as? UITextField }.first
}
private var activityIndicator: UIActivityIndicatorView? {
return textField?.leftView?.subviews.flatMap{ $0 as? UIActivityIndicatorView }.first
}
var isLoading: Bool {
get {
return activityIndicator != nil
} set {
if newValue {
if activityIndicator == nil {
let newActivityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
newActivityIndicator.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
newActivityIndicator.startAnimating()
newActivityIndicator.color = UIColor().HexToColor(hexString: BUTTON_COLOR)
newActivityIndicator.backgroundColor = UIColor.white
textField?.leftView?.addSubview(newActivityIndicator)
let leftViewSize = textField?.leftView?.frame.size ?? CGSize.zero
newActivityIndicator.center = CGPoint(x: leftViewSize.width/2, y: leftViewSize.height/2)
}
} else {
activityIndicator?.removeFromSuperview()
}
}
}
Any help please, this is Swift 3. Thanks in advance
so there a few things you are dealing with
1 Rectangular UISearchbar
either you will traverse subviews of native UISearchbar and change its right sublayers corner radiuses, but this is a hack, Apple can change that hierarchy and you will be at the beginning again
you can create your own component that will look like UISearchbar, few UIViews, and UITextfield with some UIImageViews.
there are few libraries on GitHub you can use https://github.com/CosmicMind/Samples
there is also a similar question here iOS 11 UISearchBar in UINavigationBar
2 Merge with NavBar
one way is to use UISearchController with iOS 11
or you can with your custom UISearchbar you can either add it below the NavBar in UIView, not in navigation, but the NavBar cannot be translucent in this case, because you will never achieve the same color space
you can add your custom view as custom UIView into titleView in NavBar
Extend the UISearchBar and apply the customization.
Set the UISearchBar as titleView to the NavigationController
class SearchField: UISearchBar {
override init(frame: CGRect) {
super.init(frame: frame)
// Corner radius
self.layer.cornerRadius = 2.0
self..clipsToBounds = true
// Textfield inside color.
if let searchTextField = self.value(forKey: "_searchField") as? UITextField {
// Set TextField property
// Set the corner radius for TextField (not suggested)
if let clearButton = searchTextField.value(forKey: "_clearButton") as? UIButton {
// Set the clear button property
}
}
}
}
// Use it in the ViewController.
let searchBar = SearchField()
self.navigationItem.titleView = searchBar
Related
I am very new to swift and am building a navigation view. Below is what i ran into.
currentView
The navigation bar background color is only partly yellow. How can I also make the section above it also yellow?
section should be yellow
Below is the code that I used in my viewController. I also tried in the navigation controller but it doesn't work.
self.navigationController?.navigationBar.backgroundColor = UIColor.yellow
How to set the height of the navigation bar? The search button (navigationItem.titleView) is right in the middle of the navigation bar and I want to give it more space by setting the navigation bar height. The code below is what I tried but doesn't work :(
self.tabBarController?.tabBar.frame.size.height = 50
Thanks.
you have to changed the status bar color as well. you can done this using below extension of UIApplication
extension UIApplication {
var statusBarView: UIView? {
if responds(to: Selector(("statusBar"))) {
return value(forKey: "statusBar") as? UIView
}
return nil
}
}
use above extension like this :
UIApplication.shared.statusBarView?.backgroundColor = .yellow
for iOS 13 and above
use UINavigationController extension to change status bar color :
extension UINavigationController {
func setStatusBar(backgroundColor: UIColor) {
let statusBarFrame: CGRect
if #available(iOS 13.0, *) {
statusBarFrame = view.window?.windowScene?.statusBarManager?.statusBarFrame ?? CGRect.zero
} else {
statusBarFrame = UIApplication.shared.statusBarFrame
}
let statusBarView = UIView(frame: statusBarFrame)
statusBarView.backgroundColor = backgroundColor
view.addSubview(statusBarView)
}
}
navigationController?.setStatusBar(backgroundColor: .yellow)
So I'm looking for how can I add shadow to NavigationBar and remove the bottom black line from NavigationBar? Also if I have searchBar in NavigationBar then shadow should go below to search bar. I want to make a change globally without making a change in every viewController.
https://imgur.com/a/8ogGRaf.jpg
So I already archive these changes except add a shadow below to search controller.
For Shadow:
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.layer.shadowColor = UIColor.black.cgColor
self.navigationController?.navigationBar.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
self.navigationController?.navigationBar.layer.shadowRadius = 7.0
self.navigationController?.navigationBar.layer.shadowOpacity = 0.2
For Remove a Bottom Bar:
UINavigationBar.appearance().backIndicatorImage = UIImage(named:"normal")
UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named:"normal")
This is What issue I'm getting with search Bar
https://imgur.com/a/QQ9yrbE
2.hide bottom line
public extension UINavigationBar {
/// Hide line under navigation bar
public func hideBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(self)
navigationBarImageView!.isHidden = true
}
/// Show line under navigation bar
public func showBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(self)
navigationBarImageView!.isHidden = false
}
fileprivate func hairlineImageViewInNavigationBar(_ view: UIView) -> UIImageView? {
if view.isKind(of: UIImageView.self) && view.bounds.height <= 1.0 {
return (view as! UIImageView)
}
let subviews = (view.subviews as [UIView])
for subview: UIView in subviews {
if let imageView: UIImageView = hairlineImageViewInNavigationBar(subview) {
return imageView
}
}
return nil
}
}
I am trying to make a blurred background the UITabBar for my UITabViewController, and the idea is to have it be blurred and transparent so that the views underneath can be seen scrolling by.
Unfortunately I cannot for the life of me get the tab bar to be transparent. No matter what I do, there is always some black background to the tab bar that prevents the underlying view controllers from showing through.
If I change the alpha of the UITabBar to something low I can see that the tableview is indeed behind it, however you can see that the UITabBar has some sort of background to it that is preventing the tableview from fully showing through (and I don't want to bar button items to be invisible, just the tab bar background).
How can this be?
In the custom tab bar's view did load I have:
self.tabBar.translucent = true
self.tabBar.alpha = 0.3
self.tabBar.backgroundColor = UIColor.clearColor().colorWithAlphaComponent(0.0)
self.tabBar.layer.backgroundColor = UIColor.clearColor().colorWithAlphaComponent(0.0).CGColor
self.tabBar.backgroundImage = nil
self.tabBar.shadowImage = nil
and in the AppDelegate I have:
UITabBar.appearance().barTintColor = UIColor.clearColor()
UITabBar.appearance().tintColor = kColorAccent
UITabBar.appearance().translucent = true
UITabBar.appearance().translucent = true
UITabBar.appearance().backgroundColor = UIColor.clearColor()
UITabBar.appearance().backgroundImage = nil
UITabBar.appearance().layer.backgroundColor = UIColor.clearColor().CGColor
UITabBar.appearance().shadowImage = nil
...yeah It's excessive but I want to try everything.
Any ideas on what to do?
Make a UITabBar transparent
Assign a clear image to its backgroundImage. You can use a 1x1 clear.png, or create one programmatically:
self.backgroundImage = UIImage.imageWithColor(UIColor.clearColor())
This will make the UITabBar transparent:
Add a blur effect
Insert a UIVisualEffectView as the rearmost subview.
let frost = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
frost.frame = self.bounds
self.insertSubview(frost, atIndex: 0)
This will insert a UIBlurEffect (frost):
Example
Set the Custom Class for the UITabBar of the Tab Bar Controller to FrostyTabBar.
You have a few options to supply a clearColor image. You can create a clear.png image with an alpha of 0. A programmatic elegant solution is described here.
If using a clear.png, assign it to the Background Image in the Attribute Inspector:
In Interface Builder, pick Style: Default & Translucent.
Once you take control of the background blur with a UIVisualEffectView, you can in turn supply any UIVisualEffect you so desire.
The entire FrostyTabBar class looks like this:
import UIKit
class FrostyTabBar: UITabBar {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let frost = UIVisualEffectView(effect: UIBlurEffect(style: .light))
frost.frame = bounds
frost.autoresizingMask = .flexibleWidth
insertSubview(frost, at: 0)
}
}
► Find this solution on GitHub and additional details including a 1x1 clear.png on Swift Recipes.
I found a prefect solution, you only need to subclass UITabBar and then do the following actions to clean that annoying views
class MainTabBar: UITabBar {
var cleanDone = false
override func layoutSubviews() {
super.layoutSubviews()
self.deleteUnusedViews()
}
func deleteUnusedViews() {
if !self.cleanDone {
var removeCount = 0
for (_, eachView) in (self.subviews.enumerate()) {
if NSStringFromClass(eachView.classForCoder).rangeOfString("_UITabBarBackgroundView") != nil {
eachView.removeFromSuperview()
removeCount += 1
}
if NSStringFromClass(eachView.classForCoder).rangeOfString("UIImageView") != nil {
eachView.removeFromSuperview()
removeCount += 1
}
if removeCount == 2 {
self.cleanDone = true
break
}
}
}
}
}
the only solution that worked for me was this:
UITabBar.appearance().shadowImage = UIImage()
UITabBar.appearance().backgroundImage = UIImage()
and set: (you can do this in storyboard as well)
UITabBar.appearance().barTintColor = UIColor.clear
but what i have to set in storyboard is:
tabbar : translucent -> true
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]
}
I am trying to implement UINavigationBar that changes its transparency when scrolling UITableView. At the beginning, the navigation bar should have transparent background, so the content below it should be visible (there will be an image displayed, for the example I am using solid color):
When user scrolls table view, transparency should be replaced with solid color:
Table view will contain section headers, that should act like when using non-translucent navigation bar. The header views should "stick" to navigation bar once they "touch" it from the bottom:
I have no luck with trying to implement this flow in iOS app.
For the initial state, I am setting UINavigationBar translucent property to YES, and both backgroundColor and barTintColor to clear color, which gives me what I want.
Then, when user scrolls table view, I am updating the backgroundColor and barTintColor to a color with given alpha component, computed basing on current scroll offset. I am using scrollViewDidScroll: from UIScrollViewDelegate protocol to do so. However, it changes only the background of navigation bar, leaving status bar background transparent, which is not what I want.
I can't find another way of making UINavigationBar transparent without setting translucent property to YES. Unfortunately, this changes how the section headers acts when scrolling. As navigation bar is translucent, section header views hides below it when they should "stick" to the bar like on third screenshot above.
I would appreciate any help and hints how to achieve navigation bar that acts like described or similar in Objective-C or Swift.
Assuming that you have a reference to the view above the tableView and that you don't want to interact anything in it:
var overlayView:UIView!
var offsetDenominator:CGFloat!
let TARGER_COLOR = UIColor.blackColor()
override func viewDidLoad() {
super.viewDidLoad()
if let navCtrl = self.navigationController {
self.offsetDenominator = headerView.frame.size.height - navCtrl.navigationBar.frame.height
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: 0.0)
self.overlayView = UIView(frame: self.headerView.frame)
self.overlayView.backgroundColor = overlayColor
self.view.addSubview(self.overlayView)
}
...
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let navCtrl = self.navigationController, let breakpoint = offsetDenominator {
let alpha = scrollView.contentOffset.y / breakpoint
if alpha >= 1.0 {
navCtrl.navigationBar.backgroundColor = self.TARGER_COLOR
} else {
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: alpha)
self.overlayView.backgroundColor = overlayColor
navCtrl.navigationBar.backgroundColor = UIColor.clearColor()
}
}
}
My approach is:
override func viewDidLoad() {
super.viewDidLoad()
...
self.setNavbarTransculent()
}
private func setNavbarTransculent() {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let denominator: CGFloat = 50 //your offset treshold
let alpha = min(1, scrollView.contentOffset.y / denominator)
self.setNavbar(backgroundColorAlpha: alpha)
}
private func setNavbar(backgroundColorAlpha alpha: CGFloat) {
let newColor = UIColor(red: 1, green: 1, blue: 1, alpha: alpha) //your color
self.navigationController?.navigationBar.backgroundColor = newColor
UIApplication.shared.statusView?.backgroundColor = newColor
}
extension UIApplication {
var statusView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
Swift3
var navAlpha = // Your appropriate calculation
self.navigationController!.navigationBar.backgroundColor = UIColor.red.withAlphaComponent(navAlpha)