这是一个棘手的问题。
“设置”屏幕将转到“我的颜色”屏幕,用户可以在该屏幕中为应用选择深色或浅色配色方案。进行更改后,我会从窗口中删除所有视图,然后重新添加它们以强制当前视图立即通过UIAppearance代理应用更改。因此导航栏的颜色和导航栏的文本颜色都会立即改变。
接下来,用户展开segue以返回“设置”屏幕。在“设置”屏幕上,已应用导航栏的新颜色。导航栏文本的新颜色也已应用。但是,在segue处于转换状态的短暂瞬间,导航栏仍然显示旧的文本颜色。转换完成后才会显示新的文本颜色。当导航栏的文本突然从旧颜色变为新颜色时,这会导致轻微但明显的视觉故障。
要在用户翻转开关时更新导航栏文本的颜色,请在“我的颜色”屏幕的视图控制器中运行以下代码。 (完整的项目代码在Github上https://github.com/prinomen/social_demo2)。
func switchValueDidChange(sender:UISwitch!) {
if (sender.on == true) {
colorIndex = 1 // nav bar is now black
UINavigationBar.appearance().barTintColor = black // set appearance proxy to the new color
// Run this switch to set the textColor global var to match the preferred color scheme, based on the value of colorIndex.
switch colorIndex {
case 0: // white
textColor = green
statusBarTextIsBlack = true
case 1: // black
textColor = red
statusBarTextIsBlack = false
default:
break;
}
// Update these appearance proxy items (they need the window to reload before they will manifest their changes).
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName: UIFont(name: "Avenir-Medium", size: 22)!, NSForegroundColorAttributeName: textColor]
UINavigationBar.appearance().tintColor = textColor
// Remove all views from the window and then re-add them in order to force the current view to immediately apply changes to UIAppearance.
let windows : NSArray = UIApplication.sharedApplication().windows
for window in windows as! [UIWindow] {
for view in window.subviews {
view.removeFromSuperview()
window.addSubview(view)
}
}
} else {
colorIndex = 0 // nav bar is now white
UINavigationBar.appearance().barTintColor = white // set appearance proxy to the preferred color
// Run this switch to set the textColor global var to match the preferred color scheme, based on the value of colorIndex.
switch colorIndex {
case 0: // white
textColor = green
statusBarTextIsBlack = true
case 1: // black
textColor = red
statusBarTextIsBlack = false
default:
break;
}
// Update these appearance proxy items (they need the window to reload before they will manifest their changes).
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName: UIFont(name: "Avenir-Medium", size: 22)!, NSForegroundColorAttributeName: textColor]
UINavigationBar.appearance().tintColor = textColor
// Remove all views from the window and then re-add them in order to force the current view to immediately apply changes to UIAppearance.
let windows : NSArray = UIApplication.sharedApplication().windows
for window in windows as! [UIWindow] {
for view in window.subviews {
view.removeFromSuperview()
window.addSubview(view)
}
}
}
}
除了通过外观代理更改颜色外,我还尝试通过运行此行在“设置”屏幕视图控制器的viewWillAppear
和viewWillLayoutSubviews
方法中明确设置颜色:
self.navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName: UIFont(name: "Avenir-Medium", size: 22)!, NSForegroundColorAttributeName: textColor]
但这会导致同样的问题。我觉得令人困惑的是,通过外观代理进行的其他更改会在不遇到此问题的情况下进行更新。只有titleTextAttributes
属性会受到此问题的困扰。
我认为,当转到“我的色彩”屏幕时,iOS可能会对“设置”屏幕进行某种“快照”。然后当segue反转时,使用具有旧导航条文本颜色的“快照”,并且直到segue完成后才更新新颜色。但如果这是真的,那么为什么导航栏的barTintColor
也没有遇到同样的问题呢?反向segue的处理必须有不同的方式,但我似乎无法弄明白。
有没有办法在转换发生之前将颜色更改应用于标题文本,这会影响过渡本身?
感谢您的任何见解!