5

我正在使用UIAppearanceiOS 5 中的新 API 来设置UISegmentedControl自定义图形的样式。我需要能够在执行期间将某些段设置为有时禁用,但这些UIAppearance方法似乎不允许我为UIControlStateDisabled状态设置分隔符图像。

我打电话给:

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

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

禁用选定图像

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

UISegmentedControl UI 故障

您可以清楚地看到UISegmentedControl默认使用UIControlStateNormal-UIControlStateNormal分隔线图像。

使用设置背景图像对我来说似乎非常高兴UIControlStateDisabled

[[UISegmentedControl appearance] setBackgroundImage:disabledImage
                                    forState:UIControlStateDisabled
                                    barMetrics:UIBarMetricsDefault];

(并尊重我在禁用状态下提供的图像)但不是分隔图像。有没有人遇到过这个或找到解决方案?

4

6 回答 6

3

我已经决定这一定是一个 iOS 错误,并已向Apple提交了雷达。我现在对这个问题的解决方案是删除段,而不是禁用它们。

于 2012-03-12T19:40:06.230 回答
1

有点丑陋的解决方法,但我设法用以下方法修复它,直到苹果自己修复它。

首先,您需要继承 UISegmentedControl 并添加以下内容:

@implementation MJSegmentedControl

- (void)layoutSubviews
{
    [super layoutSubviews];
    NSInteger cachedIndex = self.selectedSegmentIndex;
    self.selectedSegmentIndex = 0;
    self.selectedSegmentIndex = cachedIndex;
}

@end
于 2012-09-01T09:52:54.760 回答
0

我还没有需要使用 iOS 5 的外观控件,但如果所有其他方法都失败了,您可以将可调整大小的图像添加为分段控件的子控件以掩盖丑陋。这是一个 hack,但它可能会起作用,并且会相对向前兼容。一定要适当地设置自动调整大小的蒙版。

于 2012-03-12T01:50:51.133 回答
0

我有同样的问题,它似乎真的是一个错误。但是我找到了一个解决方案(一种解决方法)。

我已经将 XIB 文件与控制器一起使用。在 XIB 文件中,仅放置了分段控件,并且所有自定义都在-viewDidLoad方法中完成。

然后我创建了一个 UIView 子类,它代表了 XIB 中的整个视图。这使得将所有视图自定义代码移动-awakeFromNib到此 UIView 子类的方法成为可能。移动此代码后,分隔图像已正确设置。

于 2013-01-11T11:28:54.863 回答
0

正如费尔南多在此线程中所建议的那样: 在 iOS 5 中自定义 UISegmentedControl

您可以尝试通过以下方式在主队列上调度您的 UISegmentedControl 设置:

dispatch_async(dispatch_get_main_queue(),^{
    // disable part of the segmented control
    [self.eventScopeSegmentedControl setEnabled:NO forSegmentAtIndex:2];
});

我在 viewDidLoad 中做了这个,它工作了一段时间,但是当我的应用程序在启动时真的很忙时,这并不总是有效。我猜有一个竞争条件,当外观代理开始工作时,它可能仍然会恢复您所做的任何设置。

我添加了另一个丑陋的 hack 来在 viewWillAppear 中进行这个调用(在调用 super:viewWillAppear 之后),并带有一个标志(从 viewWillLoad 设置),以确保它只运行一次。

于 2013-04-10T22:44:55.517 回答
0

实际上有一种非常简单的方法可以完成这项工作。当前的行为显然是一个错误,因此这不是一个理想的解决方案,而只是一种效果很好的解决方法。即,使用额外的 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 行。

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

启用分段控制

启用分段控制

“禁用”分段控制

禁用分段控制

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

塑造 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;
}

就是这样。

-

于 2013-06-02T17:48:25.993 回答