Subclassed UISegmentedControl titleTextAttributes并不总是应用

时间:2015-11-06 09:56:55

标签: ios objective-c uisegmentedcontrol

方案

我的子类UISegmentedControl中有一个奇怪的错误。我所做的只是将UISegmentedControl子类化为删除选择/取消选择的默认指标,并使用自定义CALayer作为指标。与此同时,我修改了titleTextAttributes以补充用户界面。

问题

当视图首次出现且默认选择的索引为0时,它看起来像这样:

enter image description here

当我尝试将selectedSegmentIndex更改为1时,它变为:

enter image description here

它应该是这样的(一旦你改变selectedSegmentIndex几次就更正了):

enter image description here

titleTextAttributes这种{not}不变的行为是随机的,但是这种情况在100%的情况下发生的情况是:

  • 显示视图,并选择索引1处的细分
  • 选择最后一个细分,然后选择细分0

我没有在UISegmentedControl官方文档中找到子类注释。

示例项目HERE

注意:如果您只使用2个细分,则在选择时,您将永远不会在索引1处看到细分的标题。

3 个答案:

答案 0 :(得分:1)

确实这是一种奇怪的行为。

您可以解决此问题,在更改指示图层框架后添加对[self setNeedsLayout]的显式调用。

//
//  RBLSegmentedControl.m
//  Rabbler
//
//  Created by Utkarsh Singh on 05/11/15.
//  Copyright © 2015 Neeraj  SIngh. All rights reserved.
//

#import "NPSegmentedControl.h"

@interface NPSegmentedControl ()

@property (nonatomic, retain) CALayer* selectedIndicationLayer;

@end

@implementation NPSegmentedControl

- (instancetype)initWithItems:(NSArray *)items {

    if (self = [super initWithItems:items]) {

        self.selectedIndicationLayer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width / items.count, self.frame.size.height);
        [self addTarget:self action:@selector(segmentedControlDidChange) forControlEvents:UIControlEventValueChanged];

        NSDictionary* selectedAttributes = @{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:15],
                                             NSForegroundColorAttributeName:[UIColor whiteColor]};
        NSDictionary* deselectedAttributes = @{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:15],
                                               NSForegroundColorAttributeName:[UIColor redColor]};
        NSDictionary* highlightedAttributes = @{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:15],
                                                NSForegroundColorAttributeName:[[UIColor redColor] colorWithAlphaComponent:0.6f]};

        [self setTitleTextAttributes:deselectedAttributes forState:UIControlStateNormal];
        [self setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];
        [self setTitleTextAttributes:highlightedAttributes forState:UIControlStateHighlighted];
    }

    return self;
}

- (void) segmentedControlDidChange {

    [self animateSegmentSelectionChange];

    if (self.delegate && [self.delegate respondsToSelector:@selector(segmentedControlDidChangeSelectedSegment:)]) {

        [self.delegate segmentedControlDidChangeSelectedSegment:self.selectedSegmentIndex];
    }
}

- (void) animateSegmentSelectionChange {

    [UIView animateWithDuration:0.25
                          delay:0
                        options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState)
                     animations:^{

                         CGRect frame = self.selectedIndicationLayer.frame;
                         frame.origin.x = self.selectedSegmentIndex * [UIScreen mainScreen].bounds.size.width / self.numberOfSegments;
                         self.selectedIndicationLayer.frame = frame;

                         [self setNeedsLayout]; // <--

                     } completion:nil];
}

- (CALayer *) selectedIndicationLayer {

    if (!_selectedIndicationLayer) {

        _selectedIndicationLayer = [CALayer layer];
        _selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
        _selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
        _selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
        _selectedIndicationLayer.borderWidth = 1.5f;
        [self.layer insertSublayer:_selectedIndicationLayer atIndex:0];
    }

    return _selectedIndicationLayer;
}

- (void) setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {

    [super setSelectedSegmentIndex:selectedSegmentIndex];

    [self animateSegmentSelectionChange];
}

- (void) setIndicatorColor:(UIColor *)indicatorColor {

    self.selectedIndicationLayer.backgroundColor = indicatorColor.CGColor;
}

@end

答案 1 :(得分:0)

我将您的selectedIndicationLayer更改为此问题并解决问题

- (CALayer *) selectedIndicationLayer {

    if (!_selectedIndicationLayer) {

        _selectedIndicationLayer = [CALayer layer];
        _selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
        _selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
        _selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
        _selectedIndicationLayer.borderWidth = 1.5f;
    }

    if ([self.layer.sublayers containsObject:_selectedIndicationLayer]) {
        [_selectedIndicationLayer removeFromSuperlayer];
    }
    [self.layer insertSublayer:_selectedIndicationLayer atIndex:0];

    return _selectedIndicationLayer;
}

答案 2 :(得分:0)

只需编辑以下方法即可。

- (CALayer *) selectedIndicationLayer {

if (!_selectedIndicationLayer) {

    _selectedIndicationLayer = [CALayer layer];
    _selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
    _selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
    _selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
    _selectedIndicationLayer.borderWidth = 1.5f;
}

[self.layer insertSublayer:_selectedIndicationLayer atIndex:0];

return _selectedIndicationLayer;
}