UISegmentedControl 不尊重为 UIControlStateDisabled 设置的分隔符图像
-
12-12-2019 - |
题
我正在使用新的 UIAppearance
iOS 5 中用于样式化的 API UISegmentedControl
带有自定义图形。我需要能够在执行过程中有时设置禁用某些段,但是 UIAppearance
方法似乎不允许我为 UIControlStateDisabled
状态。
我打电话:
[[UISegmentedControl appearance] setDividerImage:disabledSelectedImage
forLeftSegmentState:UIControlStateDisabled
rightSegmentState:UIControlStateSelected
barMetrics:UIBarMetricsDefault];
在哪里 disabledSelectedImage
是来自此资源的可调整大小的图像:
然而,当我将左侧段设置为禁用时([UISegmentedControl setEnabled:forSegmentAtIndex:]
),结果是这样的:
您可以清楚地看到 UISegmentedControl
已默认使用 UIControlStateNormal
-UIControlStateNormal
分隔线图像。
我似乎非常高兴使用设置背景图像 UIControlStateDisabled
[[UISegmentedControl appearance] setBackgroundImage:disabledImage
forState:UIControlStateDisabled
barMetrics:UIBarMetricsDefault];
(并尊重我在禁用状态下提供的图像)但不尊重分隔图像。有没有人遇到过这个或找到解决方案?
解决方案
我确定这一定是 iOS 错误并已提交 雷达 与苹果公司。我现在解决这个问题的方法是删除段,而不是禁用它们。
其他提示
有点丑陋的解决方法,但我设法用以下方法修复它,直到苹果自行修复它。
首先,您需要子类化 UISegmentedControl 并添加以下内容:
@implementation MJSegmentedControl
- (void)layoutSubviews
{
[super layoutSubviews];
NSInteger cachedIndex = self.selectedSegmentIndex;
self.selectedSegmentIndex = 0;
self.selectedSegmentIndex = cachedIndex;
}
@end
我还不需要使用 iOS 5 的外观控件,但如果其他方法都失败了,您可以将可调整大小的图像添加为分段控件的子级,以掩盖丑陋之处。这是一个 hack,但它可能有效并且相对向前兼容。请务必正确设置自动调整大小蒙版。
我遇到了同样的问题,这似乎确实是一个错误。不过我找到了一个解决方案(解决方法)。
我已经将 XIB 文件与控制器一起使用。在 XIB 文件中,分段控件刚刚放置,所有自定义都在 -viewDidLoad
方法。
然后我创建了一个 UIView 子类,它代表 XIB 中的整个视图。它使得将所有视图自定义代码移动到 -awakeFromNib
此 UIView 子类的方法。移动此代码后,分隔线图像已正确设置。
正如费尔南多在此线程中所建议的:在 iOS 5 中自定义 UISegmentedControl
您可以尝试通过以下方式在主队列上分派 UISegmentedControl 设置:
dispatch_async(dispatch_get_main_queue(),^{
// disable part of the segmented control
[self.eventScopeSegmentedControl setEnabled:NO forSegmentAtIndex:2];
});
我在 viewDidLoad 中执行了此操作,并且运行良好一段时间,但是当我的应用程序在启动时非常繁忙时,这并不总是有效。我猜测存在竞争条件,当外观代理开始工作时,该条件仍可能恢复您所做的任何设置。
我添加了另一个丑陋的黑客,以使用标志(从 viewWillLoad 设置)在 viewWillAppear 中进行此调用(在调用 super:viewWillAppear 之后),以确保仅运行一次。
实际上有一个非常简单的方法可以完成此任务。当前的行为显然是一个错误,因此这不是一个理想的解决方案,而只是一个效果很好的解决方法。即,使用额外的 UIView 作为“禁用的视觉提示”。
一般步骤:
- 将 UIView 作为同级添加到 UISegmentedControl。确保 UIView 位于 UISegmentedControl 的前面
- 将所需的颜色和透明度应用到 UIView 以匹配您的应用程序皮肤
- 将 UIView 移动到 UISegmentedControl 的顶部
- 将 UIView 塑造为具有 UISegmentedControl 顶部的精确尺寸
- 对 UIView 应用圆角以镜像 UISegmentedControl 的精确形状
当应该禁用 UISegmentedControl 时,只需显示 UIView 并禁用 UISegmentedControl 上的用户交互即可。
当需要启用 UISegmentedControl 时,只需隐藏 UIView 并启用 UISegmentedControl 上的用户交互即可。
在这两种情况下,请勿更改 UISegmentedControl.enabled 属性。
请注意,这似乎有很多步骤,但所有这些都可以编码,因此在将其添加到配置分段控件方法后,添加对禁用自定义 UISegmentedControl 的支持几乎变成了 1 行。
以下是应用此解决方案时我的自定义分段控件的外观:
启用分段控制
“禁用”分段控制
以下是一些有趣的代码片段:
调整 UIView 的形状以匹配 UISegementedControl(加载时配置)
UISegmentedControl* segmentedControl = ...
//Segmented Control disabled visual cue view
UIView* view = ...
//Step #2
view.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6];
//Step #3 and #4
view.frame = segmentedControl.frame;
//Step #5
view.layer.cornerRadius = 5
view.clipsToBounds = YES;
//Ensure this is disabled by default
view.userInteractionEnabled = NO;
启用/“禁用”UISegementedControl(运行时状态更改)
BOOL segmentedControlEnabled = ...
if(segmentedControlEnabled) {
segmentedControl.userInteractionEnabled = YES;
view.hidden = YES;
} else {
segmentedControl.userInteractionEnabled = NO;
view.hidden = NO;
}
就是这样。
-