iOS 7分割器图像中的UISegmentedControl在动画期间是错误的

时间:2013-09-19 12:35:01

标签: ios iphone cocoa-touch ios7 uisegmentedcontrol

我有一个自定义的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时发生的任何想法? 谢谢?

6 个答案:

答案 0 :(得分:6)

我以类似于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的内部,但至少它会让你的代码更清洁。

答案 1 :(得分:4)

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

通过在段的图层上调用removeAllAnimations并在嵌套在每个段内的UILabel上调用removeAllAnimations,我已经能够通过删除backgroundImage和titles(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]

答案 2 :(得分:2)

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

override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
    CATransaction.setDisableActions(true)
    super.touchesEnded(touches, withEvent: event)
}

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

为了向Wyatt的答案添加更多细节,发生的事情是“分割器”图像和新的“选定”图像会在touchUp上立即更改,但之前选择的片段从“选定”图像转换为“未选定”的图像是通过动画交叉渐变来执行的。

如果你在“分频器”图像和“选定”图像之间有一个高对比度的宽“分频器”图像,这会导致恼人的闪光。

答案 5 :(得分:0)

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