【问题标题】:UISegmentedControl does not respect divider images set for UIControlStateDisabledUISegmentedControl 不尊重为 UIControlStateDisabled 设置的分隔图像
【发布时间】:2012-03-28 10:54:51
【问题描述】:

我在 iOS 5 中使用新的UIAppearance 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];

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

【问题讨论】:

  • 这看起来像一个错误。我认为你应该在 bugreport.apple.com 上提交。
  • @jfortmann 我认为你是对的,我现在更改了流程以删除段而不是禁用它们。似乎UIAppearance API for UISegmentedControl 中有很多错误

标签: ios ios5 uisegmentedcontrol uiappearance


【解决方案1】:

我已确定这一定是 iOS 错误,并已向 Apple 提交了radar。我目前对该问题的解决方案是删除段,而不是禁用它们。

【讨论】:

  • 本周早些时候我做了the same。很高兴看到我不是唯一一个。
  • @CoryKilger 我在构建此分段控件时也注意到了您的报告,但幸运的是它并没有影响到我,因为我不需要先选择第二个分段。我会通过雷达转发你的,希望我们能得到更多关注。
【解决方案2】:

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

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

@implementation MJSegmentedControl

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

@end

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 我计划在整个应用程序中使用自定义的分段控件,可能具有不同数量的分段/位置等。所以不幸的是,我认为它不适合我。
    • 为什么不创建自己的 UISegmentedControl 子类来自动添加可调整大小的图像?
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

      正如费尔南多在此线程中所建议的: Customizing UISegmentedControl in iOS 5

      您可以尝试通过以下方式在主队列中调度 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 设置)以确保它只运行一次。

      【讨论】:

        【解决方案6】:

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

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

        启用分段控制

        “禁用”分段控制

        这里有一些感兴趣的代码sn-ps:

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

        就是这样。

        -

        【讨论】:

          猜你喜欢
          • 2012-08-14
          • 1970-01-01
          • 1970-01-01
          • 2011-03-01
          • 1970-01-01
          • 2011-12-15
          • 2013-08-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多