2015-11-06 45 views
1

方案子類UISegmentedControl titleTextAttributes並不總是適用

我在子類UISegmentedControl一個奇特的錯誤。我剛剛完成的分類爲UISegmentedControl以刪除選擇/取消選擇的默認指標,並使用自定義CALayer作爲相同指標。與此同時,我修改了titleTextAttributes以補充用戶界面。

問題

當視圖首次出現的默認選擇的索引是0,它看起來像這樣:

enter image description here

當試圖改變selectedSegmentIndex 1變得:

enter image description here

,它應該是這樣的(修正一旦更改selectedSegmentIndex幾次):

enter image description here

titleTextAttributes不改變這種行爲是隨機的,但2箱子當這一切發生的時候100%的有:

  • 查看出現,而您在索引1
  • 選擇最後一段段選擇,然後選擇段0

我還沒有在UISegmentedControl官方文檔中找到子類註釋。

示例項目HERE

注意:如果您只使用2個分段,您將永遠不會在索引1處看到所選分段的標題。

回答

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 
+0

你知道真正奇怪的部分是什麼嗎?我在2天前向'setNeedsDisplay'添加了一個明確的調用,但沒有任何效果。我現在做了,它的工作。有時候我覺得宇宙恨我。謝謝您的幫助。 – n00bProgrammer

+0

@ n00bProgrammer,注意'setNeedsDisplay'不等於'setNeedsLayout'。檢查[文檔](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/) –

+0

我錯過了。感謝您指出。 22小時,直到我可以獎勵賞金。 – n00bProgrammer

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