Customizing the colors of a UISegmentedControl

后端 未结 12 1809
萌比男神i
萌比男神i 2020-12-08 07:26

Does anybody know of a way to customize the appearance of the string based UISegmentedControl? I am trying to set the background color of the cell and the text color differe

12条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-08 07:58

    Most of the answers here don't answer the specific question of how to set a button color based on selected state which implies another color is desired for unselected state. I struggled with this for quite some time and wanted to share my solution for others to use.

    My example uses a UISegmentedControl with three segments. The unselected color for all three should be the same to give it a uniform look. The selected state for the first and last segment have unique colors.

    enter image description here

    The issue is that the segmented control is not guaranteed to be in the same order so the colors will get mixed up as you select back and forth. Dan posted a solution that uses tags but unfortunately it's no longer guaranteed to work for iOS 6 and up.

    Most of this code is taken from this post. I changed it slightly to have unique selected colors.

    What makes it work is the sorting but take note of these 2 important lines for setting the selected color:

    NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
    [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
    

    - (void) updateSegmentColors
    {
        UIColor *checkColor = [UIColor colorWithRed: 29/255.0 green:166/255.0 blue:47/255.0 alpha:1.0];
        NSArray *segmentColors = [[NSArray alloc] initWithObjects:checkColor, [UIColor blueColor], [UIColor redColor], nil];
    
        UISegmentedControl *betterSegmentedControl = self.StatusControl;
    
        // Get number of segments
        NSUInteger numSegments = [betterSegmentedControl.subviews count];
    
        // Reset segment's color (non selected color)
        for( int i = 0; i < numSegments; i++ ) {
            // reset color
            [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:nil];
            [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor blueColor]];
        }
    
        // Sort segments from left to right
        NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL];
    
        // Change color of selected segment
        NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
        [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];
    
        // Remove all original segments from the control
        for (id view in betterSegmentedControl.subviews) {
            [view removeFromSuperview];
        }
    
        // Append sorted and colored segments to the control
        for (id view in sortedViews) {
            [betterSegmentedControl addSubview:view];
        }
    }
    
    
    NSInteger static compareViewsByOrigin(id sp1, id sp2, void *context)
    {
        // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
        float v1 = ((UIView *)sp1).frame.origin.x;
        float v2 = ((UIView *)sp2).frame.origin.x;
        if (v1 < v2)
            return NSOrderedAscending;
        else if (v1 > v2)
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    }
    

    I placed the code in it's own method because I'm loading these segmented controls in a table view and need to run it upon loading (existing states from storage) and when a user changes a selection. Now I just need to call [Self updateSegmentColors]; when something changes.

提交回复
热议问题