我正在使用新的 UIAppearance iOS 5 中用于样式化的 API UISegmentedControl 带有自定义图形。我需要能够在执行过程中有时设置禁用某些段,但是 UIAppearance 方法似乎不允许我为 UIControlStateDisabled 状态。

我打电话:

[[UISegmentedControl appearance] setDividerImage:disabledSelectedImage
                                    forLeftSegmentState:UIControlStateDisabled
                                    rightSegmentState:UIControlStateSelected
                                    barMetrics:UIBarMetricsDefault];

在哪里 disabledSelectedImage 是来自此资源的可调整大小的图像:

disabled-selected-image

然而,当我将左侧段设置为禁用时([UISegmentedControl setEnabled:forSegmentAtIndex:]),结果是这样的:

UISegmentedControl UI glitch

您可以清楚地看到 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 作为“禁用的视觉提示”。

一般步骤:

  1. 将 UIView 作为同级添加到 UISegmentedControl。确保 UIView 位于 UISegmentedControl 的前面
  2. 将所需的颜色和透明度应用到 UIView 以匹配您的应用程序皮肤
  3. 将 UIView 移动到 UISegmentedControl 的顶部
  4. 将 UIView 塑造为具有 UISegmentedControl 顶部的精确尺寸
  5. 对 UIView 应用圆角以镜像 UISegmentedControl 的精确形状

当应该禁用 UISegmentedControl 时,只需显示 UIView 并禁用 UISegmentedControl 上的用户交互即可。

当需要启用 UISegmentedControl 时,只需隐藏 UIView 并启用 UISegmentedControl 上的用户交互即可。

在这两种情况下,请勿更改 UISegmentedControl.enabled 属性。

请注意,这似乎有很多步骤,但所有这些都可以编码,因此在将其添加到配置分段控件方法后,添加对禁用自定义 UISegmentedControl 的支持几乎变成了 1 行。

以下是应用此解决方案时我的自定义分段控件的外观:

启用分段控制

enabled segmented control

“禁用”分段控制

disabled segmented control

以下是一些有趣的代码片段:

调整 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;
}

就是这样。

-

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top