iOS 13 Tab Bar Layer attribute is missing swift - ios

I have added shadow on Tab Bar in initial versions on layer, but on iOS 13 we have to use Appearance that don't have layer attribute, how to add Shadow now.
Shadow on top like below image.
if #available(iOS 13, *) {
let appearance = self.self.tabBarController?.tabBar.standardAppearance.copy()
appearance?.backgroundImage = UIImage()
appearance?.shadowImage = UIImage()
appearance?.shadowColor = .clear
//appearance?.layer this is missing now
if let appearance = appearance{
self.tabBarController?.tabBar.standardAppearance = appearance
}
} else {
self.tabBarController?.tabBar.shadowImage = UIImage()
self.tabBarController?.tabBar.backgroundImage = UIImage()
self.tabBarController?.tabBar.layer.shadowOpacity = 0.0
self.tabBarController?.tabBar.layer.borderWidth = 0.0
self.tabBarController?.tabBar.clipsToBounds = true
self.tabBarController?.tabBar.layer.applySketchShadow(color: UIColor(red: 15/255, green: 54/255, blue: 136/255, alpha: 1.0), alpha: 0.1, x: 0, y: 0, blur: 25, spread: 0)
self.tabBarController?.tabBar.clipsToBounds = false
}

Set clipsToBounds False will do the magic for you.
//**self.tabBarController?.tabBar.clipsToBounds = false**
if #available(iOS 13, *) {
let appearance = self.self.tabBarController?.tabBar.standardAppearance.copy()
appearance?.backgroundImage = UIImage()
appearance?.shadowImage = UIImage()
appearance?.configureWithTransparentBackground()
if let appearance = appearance{
self.tabBarController?.tabBar.standardAppearance = appearance
}
} else {
self.tabBarController?.tabBar.shadowImage = UIImage()
self.tabBarController?.tabBar.backgroundImage = UIImage()
self.tabBarController?.tabBar.clipsToBounds = false
}
self.tabBarController?.tabBar.clipsToBounds = false
self.tabBarController?.tabBar.layer.shadowOpacity = 0.0
self.tabBarController?.tabBar.layer.borderWidth = 0.0
self.tabBarController?.tabBar.layer.applySketchShadow(color: UIColor(red: 15/255, green: 54/255, blue: 136/255, alpha: 1.0), alpha: 0.1, x: 0, y: 0, blur: 25, spread: 0)

UIBarAppearance has shadowImage and shadowColor properties. Set them as desired. Right now you are setting them to have no shadow.
Also configureWithTransparentBackground means no shadow. So you are removing the shadow and then asking where the shadow is.

Try the below code in your UITabBarController class
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13, *) {
let appearance = self.tabBar.standardAppearance.copy()
appearance.backgroundImage = UIImage()
appearance.shadowImage = UIImage()
self.tabBar.standardAppearance = appearance
} else {
self.tabBar.shadowImage = UIImage()
self.tabBar.backgroundImage = UIImage()
}
//Change These values according to your requirement. This will work for all iOS versions
self.tabBar.layer.shadowColor = UIColor.lightGray.cgColor
self.tabBar.layer.shadowOpacity = 0.3
self.tabBar.layer.shadowRadius = 5
}

Related

UIKit - adding layer effect to button removes image

I have a "fake" check box that I made using UIButton and:
var mCheckState: Bool = false {
didSet {
if mCheckState == true {
self.setImage(checkedImage, for: UIControl.State.normal)
} else {
self.setImage(uncheckedImage, for: UIControl.State.normal)
}
}
}
But when I create this layer style to add shadow/highlight edge:
contentHorizontalAlignment = .left;
contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0);
setTitleColor(.black, for: UIControl.State.normal)
setTitleColor(UIColor(red: 0.85, green: 0.70, blue: 0.65, alpha: 1.0), for: UIControl.State.highlighted)
layer.backgroundColor = globalColorCG_white_background
layer.shadowColor = CGColor(gray: 1.0, alpha: 1.0)
layer.shadowOpacity = 0.8
layer.shadowRadius = globalButtonRadiusShadow * 0.75
layer.cornerRadius = globalButtonRadiusShadow
layer.shadowOffset = CGSize(width: -6.0,height: -8.0)
layer2 = CALayer(layer: layer)
layer2!.backgroundColor = globalColorCG_white_background
layer2!.shadowColor = CGColor(gray: 0.0, alpha: 1.0)
layer2!.shadowOpacity = 0.1
layer2!.shadowRadius = globalButtonRadiusShadow * 0.5
layer2!.cornerRadius = globalButtonRadiusShadow
layer2!.shadowOffset = CGSize(width: 6.0, height: 8.0)
layer2!.frame = layer.bounds
layer.insertSublayer(layer2!, at: 0)
showsTouchWhenHighlighted = true
...the image no longer renders. What should I add/fix to get the image to render again? :- )
Extra code for info:
let checkedImage = UIImage(systemName: "checkmark.square")! as UIImage
let uncheckedImage = UIImage(systemName: "square")! as UIImage
var mIsCheckBox = false
var mCheckState: Bool = false {
didSet {
if mCheckState == true {
self.setImage(checkedImage, for: UIControl.State.normal)
//self.bringSubviewToFront(checkedImage)
} else {
self.setImage(uncheckedImage, for: UIControl.State.normal)
//self.bringSubviewToFront(uncheckedImage)
}
}
}
You can bring to front your image
class ButtonSubclass: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
/**
Set other button property and layers.
*/
if let imgView = imageView {
self.bringSubviewToFront(imgView)
}
}
}
You need to add your layer2 below the button's ImageView layer.
So change this line:
layer.insertSublayer(layer2!, at: 0)
To this:
layer.insertSublayer(layer2!, below: imageView!.layer)
You may want to check the button's imageView isn't nil and in cases where it is just add as you have already:
if let imageViewLayer = imageView?.layer {
layer.insertSublayer(layer2!, below: imageViewLayer)
} else {
layer.insertSublayer(layer2!, at: 0)
}

SelectedTintColor of Segment Control is not rounded corner on iOS 13

Rounded corner is working great on iOS 12 and below, but it's broken on iOS 13. I've created a custom Segment control class.
Code:
class SegmentedControl: UISegmentedControl {
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = self.bounds.size.height / 2.0
layer.borderColor = UIColor(red: 170.0/255.0, green: 170.0/255.0, blue: 170.0/255.0, alpha: 1.0).cgColor
layer.borderWidth = 1.0
layer.masksToBounds = true
clipsToBounds = true
}
}
I've gone through this post - How to change the colors of a segment in a UISegmentedControl in iOS 13?
but I couldn't get any solution.
Screenshot:
I was facing the same issue on iOS 13. Then I dug into its view hierarchy then I found it has multiple subviews. So I made a trick for iOS 13. You have to do following changes for iOS 13 -
ChangeselectedSegmentTintColor to Clear - self.selectedSegmentTintColor = .clear
Add following code snippet inside layoutSubviews -
for i in 0...subviews.count - 1{
if let subview = subviews[i] as? UIImageView{
if i == self.selectedSegmentIndex {
subview.backgroundColor = UIColor(red: 170.0/255.0, green: 170.0/255.0, blue: 170.0/255.0, alpha: 1.0)
}else{
subview.backgroundColor = .clear
}
}
}
I hope it will help you.
Similar to other solution I have Following Sub-Class Segment control
UISegmentedControl
Which gives following result -
class OYSegmentControl: UISegmentedControl {
override func layoutSubviews(){
super.layoutSubviews()
let segmentStringSelected: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.font : UIFont.fontActionLabel(ofSize: 14.0),
NSAttributedString.Key.foregroundColor : UIColor.white
]
let segmentStringHighlited: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.font : UIFont.fontActionLabel(ofSize: 14.0),
NSAttributedString.Key.foregroundColor : #colorLiteral(red: 0.5567105412, green: 0.5807551742, blue: 0.6022000909, alpha: 1)
]
setTitleTextAttributes(segmentStringHighlited, for: .normal)
setTitleTextAttributes(segmentStringSelected, for: .selected)
setTitleTextAttributes(segmentStringHighlited, for: .highlighted)
layer.masksToBounds = true
if #available(iOS 13.0, *) {
selectedSegmentTintColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
} else {
tintColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
}
backgroundColor = #colorLiteral(red: 0.9191747308, green: 0.9334954619, blue: 0.9506797194, alpha: 1)
//corner radius
let cornerRadius = bounds.height / 2
let maskedCorners: CACornerMask = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner]
//background
clipsToBounds = true
layer.cornerRadius = cornerRadius
layer.maskedCorners = maskedCorners
let foregroundIndex = numberOfSegments
if subviews.indices.contains(foregroundIndex),
let foregroundImageView = subviews[foregroundIndex] as? UIImageView {
foregroundImageView.image = UIImage()
foregroundImageView.clipsToBounds = true
foregroundImageView.layer.masksToBounds = true
foregroundImageView.backgroundColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
foregroundImageView.layer.cornerRadius = bounds.height / 2 + 5
foregroundImageView.layer.maskedCorners = maskedCorners
}
}
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
Language: Swift 5.1
NOTE: This only works if you have outlet / frame set from Storyboard.
Frame from code will cause issues.
The extra 5 px on cornerRadius,a hack to make it better round rect.
I ended up using - https://github.com/alokc83/MASegmentedControl as my use-case was from Code only view.
Swift 5
If you use a subclass:
override func layoutSubviews() {
super.layoutSubviews()
roundCorners(radius: frame.height / 2)
if #available(iOS 13.0, *) {
selectedSegmentTintColor = .clear
} else {
tintColor = .clear
}
for (index, subview) in subviews.enumerated() {
if ((subviews[index] as? UIImageView) != nil) && index == selectedSegmentIndex {
subview.backgroundColor = .white
subview.roundCorners(radius: subview.frame.height / 2)
} else {
subview.backgroundColor = .clear
}
}
}
Conienience method:
extension UIView {
func roundCorners(radius: CGFloat) {
layer.roundCorners(radius: radius)
self.clipsToBounds = true
}
}
If you use the default segmented control, you just prefix with name of your segmented control:
mySegmentedControl.selectedSegmentTintColor = .clear
for (index, subview) in mySegmentedControl.subviews.enumerated() {
.....
}
Make a custom class for segment
class CustomSegmentedControl: UISegmentedControl {
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = self.bounds.size.height / 2.0
layer.borderColor = use_your_custom_color
layer.borderWidth = 1.0
layer.masksToBounds = true
clipsToBounds = true
for i in 0...subviews.count - 1{
if let subview = subviews[i] as? UIImageView{
if i == self.selectedSegmentIndex {
subview.backgroundColor = use_your_custom_color
}else{
subview.backgroundColor = .white
}
}
}
}}
May be this will easy to use like this
#IBOutlet weak var reminderSegmentControl: CustomSegmentedControl!
this code works for me iOS 13 - Swift 5.1
segment.layer.cornerRadius = 12
segment.layer.borderWidth = 1
segment.layer.borderColor = UIColor.black.cgColor
segment.font(name: "TheSans-Plain", size: 14)
segment.clipsToBounds = true
segment.layer.masksToBounds = true
if #available(iOS 13.0, *) {
segment.selectedSegmentTintColor = .red
}

navigation bar back ground color will change into wrong color when table view scrolls in swift 4

I seen this video on you tube
https://www.youtube.com/watch?v=rNy6aQQYbuY
But the problem is that navigation bar color will not change color into correct color that I want to be
so here is the codes
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.tintColor = .white
if #available(iOS 11.0, *) {
self.profileTV.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(scrollView.contentOffset.y)
var offset = scrollView.contentOffset.y / 150
if offset > 1 {
offset = 1
let color = UIColor(red: 181, green: 40, blue: 56, alpha: offset)
self.navigationController?.navigationBar.backgroundColor = color
UIApplication.shared.statusBarView?.backgroundColor = color
} else {
let color = UIColor(red: 181, green: 40, blue: 56, alpha: offset)
self.navigationController?.navigationBar.backgroundColor = color
UIApplication.shared.statusBarView?.backgroundColor = color
}
}
extension UIApplication {
var statusBarView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
the color after scrolling will be white But I want to be the color code that I wrote in my codes
change your code to:
func setNavigation() {
if #available(iOS 11.0, *) {
self.tV.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
self.navigationController?.navigationBar.tintColor = .red
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var offset = scrollView.contentOffset.y / 1500
if offset >= 1 {
offset = 1
self.navigationController?.navigationBar.backgroundColor = UIColor.white.withAlphaComponent(offset)
// self.navigationController?.navigationBar.alpha = offset
// print(offset - 0.399)
UIApplication.shared.statusBarView?.backgroundColor = UIColor.red.withAlphaComponent(offset)
} else {
self.navigationController?.navigationBar.backgroundColor = UIColor.white.withAlphaComponent(offset)
UIApplication.shared.statusBarView?.backgroundColor = UIColor.red.withAlphaComponent(offset)
}
}
Put this extension wherever you want :
public extension UIImage {
convenience init(withBackground color: UIColor) {
let rect: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size);
let context:CGContext = UIGraphicsGetCurrentContext()!;
context.setFillColor(color.cgColor);
context.fill(rect)
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
self.init(ciImage: CIImage(image: image)!)
}
}
It makes a UIImage using a UIColor. change the color alpha and set it as your navigationBar's backGroundImage. Here is a sample of how to use it:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
DispatchQueue.main.async {
var offset = scrollView.contentOffset.y
self.navigationController?.navigationBar.setBackgroundImage(UIImage(withBackground: UIColor.init(red: 0, green: 0, blue: 0, alpha: offset * 0.1)), for: .default)
}
}
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = UIColor(named: "BackgroundColor")
appearance.titleTextAttributes = [.foregroundColor: UIColor(named: "TextColor") ?? .white]
self.navigationController?.navigationBar.scrollEdgeAppearance = appearance
self.navigationController?.navigationBar.standardAppearance = appearance

custom background image with large titles NavigationBar in iOS 11

How do you set a custom background image for the large title NavigationBar in iOS 11? I'm using a custom subclass which I've assigned to the navigationControllers in the storyboard.
This is how I create my custom NavBar:
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationBar.tintColor = UIColor(red:1, green:1, blue:1, alpha:0.6)
self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
if #available(iOS 11.0, *) {
self.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .automatic
self.navigationBar.largeTitleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
self.navigationBar.barTintColor = UIColor.green
}
self.navigationBar.isTranslucent = false
self.navigationBar.setBackgroundImage(#imageLiteral(resourceName: "navigationBarBackground"), for: .default)
self.navigationBar.shadowImage = #imageLiteral(resourceName: "navigationBarShadow")
}
}
Strangely the setBackgroundImage(image, for: .default) doesn't work for the large titles. It worked before with iOS 10 and also if I rotate the iPhone (and activate the small NavBar) the background is back?
Edit:
The backgroundImage is still rendered but somehow hidden. Only if you start scrolling and the "normal" Navigation Bar appears, the backgroundImage is visible. Also the barTintColor is completely ignored in this case.
I had the same issue, fixed it by
Remove setBackgroundImage and use barTint color with pattern image
let bgimage = imageWithGradient(startColor: UIColor.red, endColor: UIColor.yellow, size: CGSize(width: UIScreen.main.bounds.size.width, height: 1))
self.navigationBar.barTintColor = UIColor(patternImage: bgimage!)
Get image with gradient colors
func imageWithGradient(startColor:UIColor, endColor:UIColor, size:CGSize, horizontally:Bool = true) -> UIImage? {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
if horizontally {
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
} else {
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
}
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
Finally I found solution!
Edit: Works on iOS 13 and higher
You can use it before view appears, eg: in viewDidLoad() method:
override func viewDidLoad()
{
super.viewDidLoad()
let largeTitleAppearance = UINavigationBarAppearance()
largeTitleAppearance.configureWithOpaqueBackground()
largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png")
self.navigationBar.standardAppearance = largeTitleAppearance
self.navigationBar.scrollEdgeAppearance = largeTitleAppearance
}
All that you need is:
Create UINavigationBarAppearance instance:
let largeTitleAppearance = UINavigationBarAppearance()
Apple documentation:
UINavigationBarAppearance - An object for customizing the appearance of a navigation bar.
Configure it:
largeTitleAppearance.configureWithOpaqueBackground()
"Opaque" here because we want to set colorised image (but in practice it doesn't matter, what configure will you set)
Set background image:
largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png") // Set here image that you need
Assign our largeTitleAppearance object to both standardAppearance and scrollEdgeAppearance navigationBar's fields:
self.navigationBar.standardAppearance = largeTitleAppearance // For large-navigationBar condition when it is collapsed
self.navigationBar.scrollEdgeAppearance = largeTitleAppearance // For large-navigationBar condition when it is expanded
Apple documentation:
.standardAppearance - The appearance settings for a standard-height navigation bar.
.scrollEdgeAppearance - The appearance settings to use when the edge of any scrollable content reaches the matching edge of the navigation bar.
This helped to me: https://sarunw.com/posts/uinavigationbar-changes-in-ios13/#going-back-to-old-style
In iOS 11 you no more need set BackgroundImage(Remove its declaration) if you use large titles. Instead you need use BarTintColor.
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationBar.tintColor = UIColor(red:1, green:1, blue:1, alpha:0.6)
self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
if #available(iOS 11.0, *) {
self.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .automatic
self.navigationBar.largeTitleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
self.navigationBar.barTintColor = UIColor(red:1, green:1, blue:1, alpha:1)
}
else {
self.navigationBar.setBackgroundImage(#imageLiteral(resourceName: "navigationBarBackground"), for: .default)
}
self.navigationBar.shadowImage = #imageLiteral(resourceName: "navigationBarShadow")
self.navigationBar.isTranslucent = false
}
}
Try this code (Swift 4.0):
in viewDidLoad()
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .automatic
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
} else {
//iOS <11.0
}
self.title = "Title"
self.navigationController?.navigationBar.barTintColor = UIColor(patternImage: #imageLiteral(resourceName: "nav_bg"))
self.navigationController?.navigationBar.isTranslucent = false
Piggybacking on oldrinmendez's answer - that solution works perfect for a horizontal gradient.
For a VERTICAL gradient, I was able to use the same function from oldrinmendez's answer by calling it again in scrollViewDidScroll. This continually adjusts the height of the gradient image as the user scrolls.
Start with the function from oldrinmendez :
func imageWithGradient(startColor:UIColor, endColor:UIColor, size:CGSize, horizontally:Bool) -> UIImage? {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
if horizontally {
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
} else {
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
}
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
Create an update function to call it with the options you want:
func updateImageWithGradient() {
let navBarHeight = self.navigationController?.navigationBar.frame.size.height
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let heightAdjustment: CGFloat = 2
let gradientHeight = navBarHeight! + statusBarHeight + heightAdjustment
let bgimage = imageWithGradient(startColor: UIColor.red, endColor: UIColor.orange, size: CGSize(width: UIScreen.main.bounds.size.width, height: gradientHeight), horizontally: false)
navigationController?.navigationBar.barTintColor = UIColor(patternImage: bgimage!)
}
Finally add the update function to scrollViewDidScroll & ViewDidApper: Use ViewDidAppear so the correct navigation bar height is returned
override func viewDidAppear(_ animated: Bool) {
updateImageWithGradient()
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
DispatchQueue.main.async {
updateImageWithGradient()
}
}
In Xamarin it would be like this:
this.NavigationBar.BackgroundColor = UIColor.Clear;
var gradientLayer = new CAGradientLayer
{
Frame = new CGRect(0, 0, UIApplication.SharedApplication.StatusBarFrame.Width,
UIApplication.SharedApplication.StatusBarFrame.Height + this.NavigationBar.Frame.Height),
Colors = new CGColor[]
{Constants.Defaults.Navigation.RealBlueColor.ToCGColor(), Constants.Defaults.Navigation.RealBlueColor.ToCGColor()}
};
UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
gradientLayer.RenderInContext((UIGraphics.GetCurrentContext()));
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
this.View.Layer.InsertSublayer(gradientLayer, 0);
this.NavigationBar.BarTintColor = UIColor.FromPatternImage(image);
The this.View.Layer.Insert is optional. I need it when I'm "curling" up and down an image on the NavigationBar
Changing the barTint didn't work for me so I change the layer inside navigationBar
navigationBar.layer.backgroundColor = UIColor(patternImage:
UIImage(named: "BG-Roof1")!.resizableImage(withCapInsets:
UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0), resizingMode: .stretch)).cgColor

UIBlurEffect on StatusBar only (not on UINavigationBar)

Similar to this:
How to make a Navigation Bar and Status Bar blurred (UIBlurEffect)? iOS, Swift 3
but we'd like to apply the UIBlurEffect on the StatusBar only, not the navigationbar. Is this possible?
You can get your statusBar view by following code, then try add to visual effect like here
let statWindow = UIApplication.shared.value(forKey:"statusBarWindow") as! UIView
let statusBar = statWindow.subviews[0] as UIView
// statusBar.backgroundColor = UIColor(red: 23 / 255.0, green: 0 / 255.0, blue: 154 / 255.0, alpha: 0.7)
statusBar.backgroundColor = UIColor(red: 213 / 255.0, green: 0 / 255.0, blue: 0 / 255.0, alpha: 0.7)
let statWindow = UIApplication.shared.value(forKey:"statusBarWindow") as! UIView
let statusBar = statWindow.subviews[0] as UIView
statusBar.backgroundColor = UIColor.clear
let blur = UIBlurEffect(style:.dark)
let visualeffect = UIVisualEffectView(effect: blur)
visualeffect.frame = statusBar.frame
//statusBar.addSubview(visualeffect)
visualeffect.alpha = 0.5
self.view.addSubview(visualeffect)
try this
iOS 14/iOS 13 solution: You can get your statusBar blur effect, by following code in your viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
let blurryEffect = UIBlurEffect(style: .regular)
let blurredStatusBar = UIVisualEffectView(effect: blurryEffect)
blurredStatusBar.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(blurredStatusBar)
blurredStatusBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
blurredStatusBar.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
blurredStatusBar.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
blurredStatusBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true }
Sample Image

Resources