Ios UISegmentedControl不考虑为UIControlStateDisabled设置的分割器图像

Ios UISegmentedControl不考虑为UIControlStateDisabled设置的分割器图像,ios,ios5,uisegmentedcontrol,uiappearance,Ios,Ios5,Uisegmentedcontrol,Uiappearance,我正在使用iOS 5中新的UIAppearanceAPI设计带有自定义图形的UISegmentedControl。我需要能够在执行期间设置某些要禁用的段,但是UIAppearance方法似乎不允许我为UIControlStateDisabled状态设置分割图像 我打电话: [[UISegmentedControl appearance] setDividerImage:disabledSelectedImage forLef

我正在使用iOS 5中新的
UIAppearance
API设计带有自定义图形的
UISegmentedControl
。我需要能够在执行期间设置某些要禁用的段,但是
UIAppearance
方法似乎不允许我为
UIControlStateDisabled
状态设置分割图像

我打电话:

[[UISegmentedControl appearance] setDividerImage:disabledSelectedImage
                                    forLeftSegmentState:UIControlStateDisabled
                                    rightSegmentState:UIControlStateSelected
                                    barMetrics:UIBarMetricsDefault];
其中
disabledSelectedImage
是来自此资源的可调整大小的图像:

但是,当我将左段设置为禁用时(
[uisegmentedcontrolsetenabled:forSegmentAtIndex:
),结果是:

您可以清楚地看到,
UISegmentedControl
已默认使用
UIControlStateNormal
-
UIControlStateNormal
分割图像

使用
UIControlStateDisabled

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

(并尊重我在禁用状态下提供的图像),但不尊重分割图像。有人遇到过这个问题或找到了解决方案吗?

我还没有必要使用iOS 5的外观控件,但如果其他方法都失败了,你可以添加可调整大小的图像作为分段控件的子对象,以掩盖丑陋。这是一个黑客,但它可能会工作,并将相对兼容。一定要正确设置自动调整掩码。

我认为这一定是一个iOS错误,并已向苹果公司提交了申请。我现在解决这个问题的办法是删除段,而不是禁用它们。

这是一个有点难看的解决方法,但我设法用以下方法解决了它,直到苹果自己解决了它

首先,需要将UISegmentedControl子类化,并添加以下内容:

@implementation MJSegmentedControl

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

@end

我也有同样的问题,这似乎真的是一个错误。不过,我找到了一个解决方案(解决办法)

我使用了带有控制器的XIB文件。在XIB中,刚刚放置了文件分段控件,所有定制都是在
-viewDidLoad
方法中完成的


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

正如Fernando在此线程中建议的那样:

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

dispatch_async(dispatch_get_main_queue(),^{
    // disable part of the segmented control
    [self.eventScopeSegmentedControl setEnabled:NO forSegmentAtIndex:2];
});
我在viewDidLoad中做了这项工作,它在一段时间内运行良好,但当我的应用程序在启动时非常繁忙时,它并不总是起作用。我猜,当外观代理开始工作时,仍有可能恢复您所做的任何设置


我添加了另一个丑陋的hack,在调用super:viewwillbeen后,使用一个标志(从viewWillLoad设置)在viewwillbeen中进行此调用,以确保此操作只运行一次。

实际上有一个非常简单的方法来完成此操作。当前的行为显然是一个bug,因此这不是一个理想的解决方案,而只是一个运行良好的解决方案。也就是说,使用额外的UIView作为“禁用的视觉提示”

一般步骤:

  • 将UIView作为同级添加到UISegmentedControl。确保UIView位于UISegmentedControl前面
  • 将所需颜色和透明度应用于UIView,以匹配应用程序外观
  • 将UIView移动到UISegmentedControl的正上方
  • 调整UIView的形状,使其具有UISegmentedControl顶部的精确大小
  • 将圆角应用于UIView以镜像UISegmentedControl的确切形状
  • 当应该禁用UISegmentedControl时,只需显示UIView并在UISegmentedControl上禁用用户交互

    当应该启用UISegmentedControl时,只需隐藏UIView并在UISegmentedControl上启用用户交互

    在这两种情况下,都不要更改UISegmentedControl.enabled属性。

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

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

    启用分段控制

    “禁用”分段控制

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

    塑造UIView以匹配UISegementedControl(加载时间配置)

    启用/禁用UISegementedControl(运行时状态更改)

    就这样


    -

    这看起来像个bug。我想你应该在bugreport.apple.com上存档。@jfortmann我想你是对的,我现在已经改变了流程,删除了段而不是禁用它们。似乎
    UISegmentedControl
    UIAppearance
    API中有很多bug,我计划在整个应用程序中使用定制的分段控件,可能有不同数量的段/位置等。所以不幸的是,我认为它对我不起作用。为什么不创建自己的UISegmentedControl子类来自动添加可调整大小的图像呢?我在本周早些时候做过。很高兴看到我不是唯一的一个。@CoryKilger在构建此分段控件时,我也注意到了您的报告,但幸运的是,它没有影响我,因为我不需要先选择第二个分段。我会通过雷达转发你的,希望我们能得到更多的关注。
      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;
    
    BOOL segmentedControlEnabled = ...
    
    if(segmentedControlEnabled) {
      segmentedControl.userInteractionEnabled = YES;
      view.hidden = YES;    
    } else {     
      segmentedControl.userInteractionEnabled = NO;
      view.hidden = NO;
    }