如何改變 UISegmentedControl 被選中和未被選中時的背景色與文字顏色

UISegmentedControl 是 iOS 開發的一個重要元件,而我們常常利用他來做條件的選擇,如果用 XCode 中的 Interface Build 來拉出 UISegmentedControl 畫面的話,預設只有 Tint Color 和 Background Color 可以選擇,也就是當 UISegmentedControl 中的條件被選中時,就用 TintColor 來當文字顏色,用 Background Color 來當背景色; 若是 UISegmentedControl 中的條件未被選中,則用  TintColor 來當背景色,用  Background Color 來當文字顏色。這樣對於程式開發顯然不夠用,所以我們需要一點擴充。

 

UISegmentedControl-1

▲ 當用 XCode 內建的 Interface Build 來拉出 Xib 畫面時可以選擇的選項超少

 

 

要改變這這個情況,海芋是以 updateSegmentColor 的函式來實做,在實做之前,先給大家看一下實做的成果,底下是實做的成果,當 UISegmentedControl 中的條件被選中時,呈現黑底白色,未被選中時,呈現綠底紅字。

UISegmentedControl-2UISegmentedControl-3

 

而底下是的程式碼。

- (void) updateSegmentColor
{
    UIColor* checkBackgroundColor   = [UIColor blackColor];
    UIColor* unCheckBackgroundColor = [UIColor greenColor];
    UIColor* checkTintColor         = [UIColor whiteColor];
    UIColor* unCheckTintColor       = [UIColor redColor];
    
    self.m_segment.tintColor = [UIColor clearColor];
    [self.m_segment setTitleTextAttributes:@{NSForegroundColorAttributeName:checkTintColor}
                                  forState:UIControlStateSelected];
    [self.m_segment setBackgroundImage:[self genImageWithSColor:checkBackgroundColor]
                              forState:UIControlStateSelected
                            barMetrics:UIBarMetricsDefault];
    [self.m_segment setTitleTextAttributes:@{NSForegroundColorAttributeName:unCheckTintColor}
                                  forState:UIControlStateNormal];
    [self.m_segment setBackgroundImage:[self genImageWithSColor:unCheckBackgroundColor]
                              forState:UIControlStateNormal
                            barMetrics:UIBarMetricsDefault];
}
/**利用 Color 產生影像*/
- (UIImage*) genImageWithSColor: (UIColor*) color
{
    CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return theImage;
}

 

這段程式碼其實先定義 UISegmentedControl 被選中時和未被選中時的文字顏色和背景顏色,再使用 UISegmentedControl 內建的兩個函式來更新背景色和文字顏色

- (void)setTitleTextAttributes:(nullable NSDictionary *)attributes forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- (void)setBackgroundImage:(nullable UIImage *)backgroundImage forState:(UIControlState)state barMetrics:(UIBarMetrics)barMetrics NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;

 

我們要加入切換時的動作,所以別忘了在 ViewDidLoad 加入監聽事件。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [self.m_segment addTarget:self
                       action:@selector(onSegmentClick)
             forControlEvents:UIControlEventValueChanged];
}

 

以及在程式中新增一個監聽的函式。

- (void) onSegmentClick
{
    [self updateSegmentColor];
}

 

當然也別忘了在 viewDidAppear 時呼叫 updateSegmentColor 函式喔!

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear: animated];
    [self updateSegmentColor];
}

 

另外,有些人可能會想在 UISegmentedControl 選擇時加底線,則是可以在 viewDidLayoutSubviews 時使用下列程式碼。

/** Override */
- (void) viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        //Background Thread
        dispatch_async(dispatch_get_main_queue(), ^(void){
            //更新Segment顏色
            [self updateSegmentBottomColor];
        });
    });
}

 

接著,加入以下的函式啦!

- (void) updateSegmentBottomColor
{
    [self remoeveSegmentBottomColor];
    
    // Creating new layer for selection
    self.m_bottomBorder             = [CALayer layer];
    self.m_bottomBorder.borderColor = [UIColor redColor].CGColor;
    self.m_bottomBorder.borderWidth = 2.0;
    
    // Calculating frame
    CGFloat width            = 1.0 * self.m_Segment.frame.size.width/self.m_Segment.numberOfSegments;
    CGFloat x                = 1.0 * self.m_Segment.selectedSegmentIndex * width;
    CGFloat y                = 1.0 * self.m_Segment.frame.size.height - self.m_bottomBorder.borderWidth;
    self.m_bottomBorder.frame= CGRectMake(x, y,width, self.m_bottomBorder.borderWidth);
    
    // Adding selection to segment
    [self.m_Segment.layer addSublayer:self.m_bottomBorder];
}

- (void) remoeveSegmentBottomColor
{
    if (nil == self.m_bottomBorder){
        return;
    }
    
    [self.m_bottomBorder removeFromSuperlayer];
    self.m_bottomBorder = nil;
}

 

同樣的,在 onSegmentClick 加入更新事件喔!

- (void) onSegmentClick
{
    [self updateSegmentColor];
    [self updateSegmentBottomColor];
}

參考資料:http://stackoverflow.com/questions/6496441/creating-a-uiimage-from-a-uicolor-to-use-as-a-background-image-for-uibutton

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments