我需要对状态和导航栏全局应用渐变,并使其适应方向变化。因为我希望这是全局的,所以我尝试使用UIAppearance
。令人惊讶的是,UIAppearance
并不容易做到。
在“人像”中看起来很棒,但是在“风景”中时渐变太大,因此您看不到整个东西:
这是我的代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let navigationBarAppearance = UINavigationBar.appearance()
navigationBarAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationBarAppearance.isTranslucent = false
navigationBarAppearance.tintColor = UIColor.white
let status_height = UIApplication.shared.statusBarFrame.size.height
let gradientLayer = CAGradientLayer(frame: CGRect(x: 0, y: 0, width: 64, height: status_height + 44), colors: [UIColor.init(hex: "005382"), UIColor.init(hex: "00294B")])
let layerImage = gradientLayer.createGradientImage()
navigationBarAppearance.barTintColor = UIColor(patternImage: layerImage ?? UIImage())
}
我正在使用此扩展程序:
extension CAGradientLayer {
convenience init(frame: CGRect, colors: [UIColor]) {
self.init()
self.frame = frame
self.colors = []
for color in colors {
self.colors?.append(color.cgColor)
}
startPoint = CGPoint(x: 0, y: 0)
endPoint = CGPoint(x: 0, y: 1)
}
func createGradientImage() -> UIImage? {
var image: UIImage? = nil
UIGraphicsBeginImageContext(bounds.size)
if let context = UIGraphicsGetCurrentContext() {
render(in: context)
image = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
return image
}
}
我知道我可以检查方向,然后相应地更改渐变,但是我需要在每个视图控制器上执行此操作,以免破坏使用UIAppearance
并能够在一处完成的目的
我发现大多数SO线程都提供了在视图控制器级别(而不是全局级别)上进行顶部栏渐变的解决方案。
编辑:
在我的UITabBarController
上尝试了@Pan Surakami的答案,但我仍然有白色导航栏:
这是我的Storybaord设置:
和代码:
class MenuTabBarController: UITabBarController {
var notificationsVM = NotificationsVModel()
var hasNewAlerts: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
setTabs()
styleUI()
notificationsVM.fetchData { (success, newNotifications) in
if success {
self.hasNewAlerts = newNotifications.count > 0 ? true : false
DispatchQueue.main.async {
if let tabBarItems = self.tabBar.items {
for (_, each) in tabBarItems.enumerated() {
if each.tag == 999 { //only update the alerts tabBarItem tag == '999'
self.updateAlertBadgeIcon(self.hasNewAlerts, each)
}
}
}
}
}
}
}
fileprivate func setTabs() {
let tab1 = GradientNavigationController(rootViewController: FeedViewController())
let tab2 = GradientNavigationController(rootViewController: NotificationsTableViewController())
let tab3 = GradientNavigationController(rootViewController: SearchViewController())
let tab4 = GradientNavigationController(rootViewController: ComposeDiscussionViewController())
UITabBarController().setViewControllers([tab1, tab2, tab3, tab4], animated: false)
}
func updateAlertBadgeIcon(_ hasAlerts: Bool, _ item: UITabBarItem) {
if hasAlerts {
item.image = UIImage(named: "alert-unselected-hasAlerts")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
item.selectedImage = UIImage(named: "alert-selected-hasAlerts")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
} else {
hasNewAlerts = false
item.image = UIImage(named: "alert-unselected-noAlerts")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
item.selectedImage = UIImage(named: "alert-selected-noAlerts")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
}
}
// UITabBarDelegate
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if item.tag == 999 { //alerts tabBarItem tag == '999'
updateAlertBadgeIcon(hasNewAlerts, item)
}
if item.tag == 0 { //Feed Item clicked
if let feedNav = children[0] as? UINavigationController, let feedVC = feedNav.viewControllers[0] as? FeedViewController {
feedVC.tableView.reloadData()
}
}
}
func styleUI() {
UITabBar.appearance().backgroundImage = UIImage.colorForNavBar(color:.lightGrey4)
UITabBar.appearance().shadowImage = UIImage.colorForNavBar(color:.clear)
tabBar.layer.shadowOffset = CGSize.zero
tabBar.layer.shadowRadius = 2.0
tabBar.layer.shadowColor = UIColor.black.cgColor
tabBar.layer.shadowOpacity = 0.30
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor : UIColor.grey2,
NSAttributedString.Key.font: UIFont(name: "AvenirNext-DemiBold", size: 12) as Any],
for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor : UIColor.darkSapphire,
NSAttributedString.Key.font: UIFont(name: "AvenirNext-DemiBold", size: 12) as Any],
for: .selected)
}
}
答案 0 :(得分:0)
一种实现方法是子类UINavigationController
。
class GradientNavigationController: UINavigationController {}
traitCollectionDidChange
方法。class GradientNavigationController: UINavigationController {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let status_height = UIApplication.shared.statusBarFrame.size.height
let gradientLayer = CAGradientLayer(frame: CGRect(x: 0, y: 0, width: 64, height: status_height + 44), colors: [[UIColor.init(hex: "005382"), UIColor.init(hex: "00294B")])
let layerImage = gradientLayer.createGradientImage()
self.navigationBar.barTintColor = UIColor(patternImage: layerImage ?? UIImage())
}
}
UINavigationController
。可以在Storiboard上更改自定义子类,或者在代码中使用它。 编辑:
您的UITabBarController
由情节提要配置。因此,setTabs()
以这种方式使用是没有意义的。它只是创建UITabBarController
的另一个副本,然后将其删除。我将其作为嵌入控制器的示例进行了展示。
setTabs()
。 GradientNavigationController
。