如何防止使用 UIAppearance 和 UIView 的 tintColor 更改所有 UITabBar 图标颜色?

Posted

技术标签:

【中文标题】如何防止使用 UIAppearance 和 UIView 的 tintColor 更改所有 UITabBar 图标颜色?【英文标题】:How to prevent using UIAppearance with UIView's tintColor from changing all UITabBar icon colours? 【发布时间】:2015-10-14 16:02:12 【问题描述】:

如果我执行UIView.appearance().tintColor = ...,选项卡栏中所有图标的 tintColor 将从正常的非活动灰色状态更改为我设置的色调颜色。

我不明白为什么会这样。我只是在更改应用程序的色调,默认情况下色调不会使所有标签栏图标看起来都处于活动状态。

如何阻止它这样做?我希望色调颜色发生变化,但未选择的选项卡保留非活动颜色。

【问题讨论】:

【参考方案1】:

我希望你现在已经找到了解决方案,但无论如何,这是我的两分钱。

Interface Builder 不会在任何地方使用 UIAppearance API(据我所知)。但是,它确实会在某些对象上设置属性,以便在它们被实例化时应用到它们。

文件检查器中有一个“全局色调”属性,用于控制***默认值tintColor。值得注意的是,除非明确告知要使用不同的颜色(无论是通过UIView.appearance() 还是仅仅通过UIView.tintColor),子视图都会从其父视图继承tintColor。请记住,这条链在视图层次结构中继续向上,直到它遇到具有tintColor 的东西。通常,它最终击中的是UIWindow,它具有Apple 非常喜欢的默认蓝色。状态的任何调暗或临时重新着色都是从视图本身或近亲继承的。这一点很重要。

还需要注意的是,您可以在UIViewController 中通过覆盖tintColorChanged() 方法来响应此问题,只要发生这种情况就会调用该方法。通过弄乱UIView.appearance(),您有效地禁用了层次结构中每个视图的继承链,并让每个视图都为自己的颜色而自生自灭。在我看来,至少有两种方法可能会阻止UITabBar 正确表示选项卡的状态:

首先,标签栏在引擎盖下具有着色图像视图,它们从父 UITabBar 继承其着色颜色。即使他们可以从标签栏获得特定于州的颜色,这个可怜的东西也没有什么不同的东西可以告诉他们,除了“你被赋予了一种颜色,你会尊重这种颜色!”,然后是耳光和鞭打声,此时他们会闷闷不乐,不知道比以前更多。通过禁用分层tintColor 继承系统,您可以禁用状态。这不好。不要那样做。

其次,通过为每个 UIView 无论状态设置色调颜色,您已经告诉标签栏项目保持该颜色无论状态如何。这不好。也不要那样做。

如果您使用的是 Interface Builder(或 Storyboards,如果您愿意),我建议您在 File Inspector 中设置该全局色调颜色,然后将其保留。这仍然可以按照您想要的方式设置您的色调,同时避免这些不良观点免受家庭虐待。

如果您需要在哪里找到 File Inspector 或 Global Tint 选项的屏幕截图,我建议您在 Xcode 右侧的侧边栏附近寻找。一点点闲逛不会伤害任何人(电影除外)。

【讨论】:

这太棒了!多年来一直在使用 UIView.appearance().tintColor 进行样式设置,但它总是感觉有点笨拙(更不用说色调颜色的奇怪问题),现在我知道为什么了。这感觉更正确。谢谢!【参考方案2】:

当您说“更改应用程序的色调”时,您是什么意思?

UIView 外观代理正在按照您的指示行事。您要求它在您的应用中设置所有UIViews 中的tintColor,其中包括您的UITabBar 中的那些视图。

听起来您实际上并不想更改所有UIViews 中的tintColor,而是想针对特定的子集。您应该查看 appearanceForTraitCollection 或(现已弃用)appearanceWhenContainedIn 方法。

【讨论】:

不,当我使用情节提要检查器设置所有视图的外观时,它不会将未选择的 UITabBarItems 设置为灰色。我只是希望它像默认的应用程序行为那样设置活动的。 我不清楚您要完成什么。你应该发布一些代码。 原始帖子中的代码是重现此代码所需的唯一代码。默认情况下,ios 将全局色调设置为蓝色。到处都是蓝色的活跃状态。当您有标签栏时,图标在选中时为蓝色,在未选中时为非活动灰色。我想将此行为更改为红色。我的印象是使用原始问题中的代码,但它也设置了标签栏的未选中状态,而默认行为则没有。我的问题是如何防止这种情况发生? 听起来你假设故事板检查员在后台使用UIView.appearance()。我几乎可以肯定那不是真的。你有任何证据支持这一点吗?根据 Apple 关于 UIAppearance 的文档“使用 UIAppearance 协议获取类的外观代理。您可以通过向类的外观代理发送外观修改消息来自定义类实例的外观。”更改 UIView 外观代理上的 tintColor 会影响应用程序中的每个 UIView,包括那些组成标签栏的 UIView。它是您问题的笨拙的非解决方案

以上是关于如何防止使用 UIAppearance 和 UIView 的 tintColor 更改所有 UITabBar 图标颜色?的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 防止 UIAppearance 设置更改 UIWebView 输入附件视图

使用 UIAppearance 和切换主题

不需要时如何摆脱 UIAppearance?

如何使用 UIAppearance 设置 ViewController 的 backgroundColor

检查 UIAppearance 的可用性

如何使用 UIappearance 在根视图控制器中获取透明导航栏