17

我有一个自定义 UISegmentedControl。在 iOS 6 及以下版本中,它工作正常。在 iOS 7 下,它看起来很好,直到我按下控件,此时,分隔线图像在一瞬间看起来很奇怪。

这是我的代码:

UIImage *segmentSelected = [[UIImage imageNamed:@"segcontrol_sel.png"]
                                resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
    UIImage *segmentUnselected = [[UIImage imageNamed:@"segcontrol_unsel.png"]
                                  resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
    UIImage *segmentSelectedUnselected =
    [UIImage imageNamed:@"segcontrol_sel_uns.png"];
    UIImage *segUnselectedSelected =
    [UIImage imageNamed:@"segcontrol_uns_sel.png"];

    [[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
                                               forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
    [[UISegmentedControl appearance] setBackgroundImage:segmentSelected
                                               forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
    [[UISegmentedControl appearance] setBackgroundImage:segmentUnselected
                                               forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];

    [[UISegmentedControl appearance] setDividerImage:segUnselectedSelected
                                 forLeftSegmentState:UIControlStateNormal // | UIControlStateHighlighted
                                   rightSegmentState:UIControlStateSelected
                                          barMetrics:UIBarMetricsDefault];
    [[UISegmentedControl appearance] setDividerImage:segUnselectedSelected
                                 forLeftSegmentState:UIControlStateHighlighted
                                   rightSegmentState:UIControlStateSelected
                                          barMetrics:UIBarMetricsDefault];
    [[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
                                 forLeftSegmentState:UIControlStateSelected
                                   rightSegmentState:UIControlStateNormal //| UIControlStateHighlighted)
                                          barMetrics:UIBarMetricsDefault];
    [[UISegmentedControl appearance] setDividerImage:segmentSelectedUnselected
                                 forLeftSegmentState:UIControlStateSelected
                                   rightSegmentState:UIControlStateHighlighted
                                          barMetrics:UIBarMetricsDefault];

    UIFont *font = [UIFont systemFontOfSize:16.0f];
    UIColor *textColor = [UIColor darkGrayColor];
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                font, @"NSFontAttributeName",
                                textColor, @"NSForegroundColorAttributeName",
                                nil];

    [[UISegmentedControl appearance] setTitleTextAttributes:attributes
                                                   forState:UIControlStateNormal];

当我按下 UISegmentedControl 时会发生什么可能会导致分隔线显示错误的任何想法?谢谢?

4

6 回答 6

7

我以类似于 user2128193 描述的方式解决了这个问题,但是我没有为值更改事件添加目标,而是将 UISegmentedControl 子类化并添加了这两个方法:

- (void)sendActionsForControlEvents:(UIControlEvents)controlEvents
{
    [super sendActionsForControlEvents:controlEvents];

    if (controlEvents & UIControlEventValueChanged) {
        [self removeAnimationsRecursivelyForView:self];
    }
}

- (void)removeAnimationsRecursivelyForView:(UIView *)view
{
    [view.layer removeAllAnimations];

    for (UIView *subview in [view subviews]) {
        [self removeAnimationsRecursivelyForView:subview];
    }
}

显然这仍然不是一个完美的解决方案,因为它依赖于 UISegmentedControl 的内部结构,但至少它会让你的代码更干净一些。

于 2014-08-12T17:32:54.700 回答
4

TL;DR 只需删除每个片段中的所有动画。请参阅下面的代码

我已经能够通过在段的图层上调用 removeAllAnimations 并在嵌套在每个段内的 UILabel 上调用 removeAllAnimations 来删除背景图像和标题 (UILabel) 的默认动画,从而解决了这个问题。我将此代码放置在触发 UISegmentedControl valueChanged 事件时调用的 IBAction 方法中。

- (IBAction)tabSelected:(id)sender
{
    UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;

    for (UIView *segment in [segmentedControl subviews]) {
        [segment.layer removeAllAnimations];

        for (UIView *view in [segment subviews]) {
            if ([view isKindOfClass:[UILabel class]]) {
                [view.layer removeAllAnimations];
            }
        }
    }
}

我没有在 UIImage 的内容上对此进行过测试,但我认为只要你更改这一行,它就不会起作用:

[view isKindOfClass:[UILabel class]

像这样匹配 UIImage 类:

[view isKindOfClass:[UIImage class]
于 2013-12-18T09:53:29.653 回答
2

我通过覆盖touchesEnded子类并禁用 CATransaction 动画解决了这个问题

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
    CATransaction.setDisableActions(true)
    super.touchesEnded(touches, withEvent: event)
}
于 2015-06-26T13:04:56.220 回答
1

我遇到了类似的问题,并发现发生了两件事。您已经处理过其中之一(为突出显示/选定的组合设置图像)。另一个是UISegmentedControl当你选择一个新的段时会突出显示颜色,就像你选择 UITableViewCells 时所做的那样。而且,即使我已经定制了所有的艺术和文字,它仍然会褪色为深色(我的文字甚至会反转)然后它又回来了。在那个淡入淡出的过程中,我的隔板的边缘很容易看到。

我必须在模拟器中打开慢速动画才能更清楚地看到这一点。不幸的是,我还没有找到禁用这些默认动画的方法。

于 2013-09-26T00:59:58.347 回答
1

为了给怀亚特的答案添加更多细节,正在发生的事情是“分隔符”图像和新的“选定”图像在 touchUp 时立即更改,但是先前选择的片段从“选定”图像过渡到“未选定”图像" 图像通过动画淡入淡出执行。

如果您有一个宽“分隔线”图像,并且“分隔线”图像和“选定”图像之间的对比度很高,这会导致令人讨厌的闪光。

于 2014-02-06T21:54:22.227 回答
0

尝试设置段控件的 tintcolor 属性。我有这个问题。我将色调颜色设置为选择颜色,并且没有为分隔线设置图像。由于这是 IOS 7,您可以为 IOS 7 执行此操作,并为 IOS 6 保留分隔图像代码。为了清楚起见,我说的是 UISegmentControl 的 tintcolor 实例级别属性。

于 2014-02-11T23:35:47.597 回答