Custom UITabBar shows a white line below UITabBarItem in iOS10 only - background-image

Since iOS10 has been release we have an issue with one of our project. The customised UITabBar shows a white line below the UITabBarItems, I have tried numerous ways to remove this line, including solutions from stack overflow:
UITabBar.appearance().backgroundImage = UIImage(named: "menu-background")
UITabBar.appearance().layer.borderWidth = 0
UITabBar.appearance().clipsToBounds = true
as well as
UITabBar.appearance().shadowImage = UIImage()
Here is a screenshot of the UITabBar, playing tricks on us

Related

Is this new navigation bar behaviour in xcode 11 beta a bug or intended?

I noticed after compiling one of my apps in Xcode 11 beta, that navigation bars have no background when prefersLargeTitles is set. Is this intended behavior?
I noticed this is how the messages app works now when scrolling down and a large title is visible there is no nav bar background.
Here is the code used to set up the navBar attributes:
override func viewWillAppear(_ animated: Bool) {
let textAttributes = [NSAttributedString.Key.foregroundColor:ThemeManager.shared.default1]
self.navigationController?.navigationBar.largeTitleTextAttributes = textAttributes
self.navigationController?.navigationBar.titleTextAttributes = textAttributes
self.navigationController?.navigationBar.tintColor = ThemeManager.shared.default1
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationController?.navigationBar.prefersLargeTitles = true
let nav = self.navigationItem
nav.title = "My Profile"
}
Here are a couple of images showing the difference:
left, compiled on Xcode 10, right, Xcode 11 beta:
Once you scroll up on the 11 Beta version, the background fades back in. Note that apps that are not compiled in Xcode 11 beta will still behave in the normal way, only changes after compiling for some reason. Is this intended, and how would I bring back the original behavior?
This is intended behavior for iOS 13.
Apple's idea (terrible in my opinion) is that the title should merge with the content to show that it is related. Once you start scrolling, when content goes behind the title bar then the title bar will take the "correct" appearance.
The reason this is terrible is because everyone has currently planned all of their UI without this behavior. So the new behavior should be opt-in instead of forcing everyone to opt-out (i.e. the change breaks everyone's code and if you're going to break everyone's code at least you should be clear about how to keep the tried and true behavior of the last 10 years).
As in your case, the result looks horrible. The result looks horrible in my case too.
Apple doesn't give answers but says that you should be using
- scrollEdgeAppearance
From UINavigationBar in order to control the appearance of the bar when content is aligned top-of-content to bottom-of-navbar ... in my case this method returns nil though so I'm currently unsure how we're supposed to use this.
This seems to be discussed here as well:
New UINavigationBar appearance in detail pane of UISplitViewController in iOS 13
So the current workaround would seem to be this in your view controller:
- (void)viewDidLoad;
{
[super viewDidLoad];
if (#available(iOS 13,*)){
UINavigationBar *bar =self.navigationController.navigationBar;
bar.scrollEdgeAppearance = bar.standardAppearance;
}
}
It works, but if it's the intended approach, I don't know...
EDIT:
Doing this does seem to block any additional direct customization to the UINavigationBar as has been noted. Possible that adjusting the scrollEdgeAppearance from here is the way to go. Ugly. Ugly. Ugly.
EDIT: Progress... this is working now for managing the background. You need to call this instead of setting barTint directly.
#interface UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
#end
#implementation UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
{
self.tintColor = fg;
self.barTintColor = bg;
if (#available(iOS 13,*)){
// we need to tell it to adopt old style behavior first
UINavigationBarAppearance *appearance = self.standardAppearance;
appearance.backgroundColor = bg;
NSDictionary *attributes = self.titleTextAttributes;
appearance.titleTextAttributes = attributes;
attributes = self.largeTitleTextAttributes;
appearance.largeTitleTextAttributes = attributes;
self.scrollEdgeAppearance = appearance;
self.standardAppearance = appearance;
self.compactAppearance = appearance;
}
}
#end
I'm not entirely sure yet on the text attributes but it seems to flow from the background color. It's a complete PITA.
It would be nicer to set this as a subclass and override barTint but of course a lot of the UIKit objects create these bars themselves so you won't get the subclass.
Swift version of dbquarrel's solution.
First declare your textAttributes:
let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]
Use these in a UINavigationBarAppearance() to enable you to change the colour of the text in 3 different modes (scollEdge, standard and compact).
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.largeTitleTextAttributes = textAttributes
appearance.titleTextAttributes = textAttributes
let bar = self.navigationController?.navigationBar
bar?.scrollEdgeAppearance = appearance
bar?.standardAppearance = appearance
bar?.compactAppearance = appearance
} else {
// Fallback on earlier versions
}
}

Transparent NSCollectionView Background

I'm again struggling with setting NSViews background colors to transparent. I have a NSCollectionView as part of NSClipView which is part of a NSScrollview. My MainViewController has an outlet to the collectionView. With adding the two lines of code and after compiling the background is sometimes transparent but most of the times not:
view.wantsLayer = true
collectionView.layer?.backgroundColor = NSColor.clear.cgColor
I also tried to select/de-select the "Draw Background" property of the NSScrollView in the IB without any effects.
What do I miss here.
I struggled a bit attempting to get my NSCollectionView background "transparent" #JFS solution pointed me in the right direction: and I finally achieved it by setting both the parent scrollView and the collectionView backgrounds:
cvScrollView.backgroundColor = NSColor.clear
collectionView.backgroundColors = [NSColor.clear]
Ok, after a long evil trial and error phase I found a solution at least for myself. There are two background colors to set in order to have the proper behavior:
the background color of the NSScrollView:
the NSCollectionView primary color:
Both have to be set appropriately. At the point I set both to the same color I got the background I want. With setting only the ScrollView background color there was still the white background when scrolling the items in the CollectionView.
To make clear background for NSScrollView, the best option in Swift 4.2 is "Not draw a background". Let's get to view a programmatically example:
let scrollView = NSScrollView()
scrollView.drawsBackground = false
scrollView.contentView.drawsBackground = false
NSCollectionView has background for sections, so you need to specify colors for sections
let collectionView = NSCollectionView()
collectionView.backgroundColors = [.clear]
If you set backgroundColors to nil or to empty array, the background color is set by default to white.
If you set a background view for NSCollectionView, this array is ignored
You could try to put a NSView with frame zero as a backgroundView for NSCollectionView

Why I cannot make my UITabBarController blurred?

I have a UITabBar and I want to make it blurred. I wrote the following code:
import UIKit
class TabBarController:UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let blur = UIBlurEffect(style: UIBlurEffectStyle.Light)
let blurView = UIVisualEffectView(effect: blur)
blurView.frame = self.view.bounds
blurView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.view.layer.insertSublayer(blurView, atIndex: 0)
}
}
but somehow the last line throws error:
Cannot convert value of type 'UIVisualEffectView' to expected argument
type 'CALayer'
how can I fix that?
I changed the last line to:
self.tabBar.addSubview(blurView)
but now the whole tabbar is blurred (even with icons and they are not visible). When I changed this line to:
self.tabBar.sendSubviewToBack(blurView)
then the tabbar is visible, but not blurred. I want to achieve effect from accepted answer from here Black background on transparent UITabBar but here it is uitabbar and I'm using uitabbarcontroller... Can you help me with applying blur in my case?
You just add the blur view as a subview:
self.view.addSubview(blurView)
Since you just want to blue the tab bar and this class is a tab bar controller, you can do:
self.tabBar.addSubview(blueView)
You also need to change the frame:
blurView.frame = self.tabBar.bounds
why don't you just use the barTintColor property on your TabBarController?
self.tabBar.translucent = true
self.tabBar.barTintColor = UIColor.blackColor()
You don't even need to subclass UITabBarController. You can call this on any UIViewController.
self.tabBarController?.tabBar.translucent = true
self.tabBarController?.tabBar.barTintColor = UIColor.blackColor()
If I understood correctly from the following comment that you posted, you want to change the UITabBar to be black in colour but still blurred.
And yes, I noticed that the UITabBarController is blurred by default, but I would like to make it blurred with specific style (.Dark).
Doing this since iOS 7 has actually become quite easy. Simply change the barStyle of your UITabBar to .black. Put the following code in your UIViewController's viewDidLoad method (note that UITabBar is translucent by default, so you don't need to specify that again).
tabBarController?.tabBar.barStyle = .black
If you want to set it back to the regular, white barStyle, change it back to .default.
tabBarController?.tabBar.barStyle = .default
You may even do this from within Interface Builder by selecting the Tab Bar in your UITabBarController's hierarchy and changing its Style to Black.
I have a solution, all you need is configure your UITabBar as following:
// next code will make tabBar fully transparent
tabBar.isTranslucent = true
tabBar.backgroundImage = UIImage()
tabBar.shadowImage = UIImage() // add this if you want remove tabBar separator
tabBar.barTintColor = .clear
tabBar.backgroundColor = .black // here is your tabBar color
tabBar.layer.backgroundColor = UIColor.clear.cgColor
If you want to add blur, do this:
let blurEffect = UIBlurEffect(style: .dark) // here you can change blur style
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.frame = tabBar.bounds
blurView.autoresizingMask = .flexibleWidth
tabBar.insertSubview(blurView, at: 0)
As a result:
Attach bottom constraint to the bottom of the view instead of Safe Area
It just might not be a problem with your TabBar but with tableView constraints.
Tab bar is blurred by default.

Change Background Color Status Bar iOS

So, I'm trying to make this:
i tried using UIView in back of Status bar and set the color to orange, but when running, The UIView displayed right under the status bar, so it's still White
i'm trying many solution in the internet but none of them work. Yes it works but when i move to other view controller and back again, The color dissapeared. What should I do? i'm using swift
UIApplication.shared.statusBarStyle = .lightContent
UINavigationBar.appearance().clipsToBounds = true
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
statusBar.backgroundColor = UIColor.orange
Try using this code in your appDelegate's method application didFinishLaunchingWithOptions

UITabBarController customisation page top bar colour swift

How do I change the colour of the top bar of the customisation page of the more view controller. Please see the linked image. Sorry I can't post image here because of my low reputation.
Screenshot Image
Edited with more info:
I have managed to change the background color using the following code. But cant change the color of the top bar.
func tabBarController(tabBarController: UITabBarController, willBeginCustomizingViewControllers viewControllers: [AnyObject]) {
var editView : UIView = tabBarController.view.subviews[1] as! UIView
editView.backgroundColor = UIColor.blackColor()
}
Basically 2 Ways you can achieve this if you are using Global Unique colour in the app for All navigation bar
Use this Solution on App Launch:
UINavigationBar.appearance().barTintColor = UIColor.redColor()
Or if you want to change the Color of More navigationcontroller only then
Use this Solution by getting the Tabbar Reference :
self.tabBarController?.moreNavigationController.navigationBar.barTintColor = UIColor.greenColor()
You can use second solution in the First viewcontroller of the Tab, because that contains your tabbar reference