Customize UISegmentedControl on iOS 8

2019-05-10 23:33发布

问题:

iOS 7 and 8 seem to make the old ways of customizing UISegmentedControl not work entirely. I've been setting the divider images and everything like I always have in the past, but it appears that there are some new states that didn't exist in previous iOS versions, and as a result there are some weird visual effects.

Here's the code that I'm using

// Set divider images
    self.setDividerImage(UIImage(named: "SegmentedControlNoneSelected"), forLeftSegmentState: .Normal, rightSegmentState: .Normal, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlRightSelected"), forLeftSegmentState: .Normal, rightSegmentState: .Selected, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlRightSelected"), forLeftSegmentState: .Normal, rightSegmentState: .Highlighted, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlLeftSelected"), forLeftSegmentState: .Selected, rightSegmentState: .Normal, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlBothSelected"), forLeftSegmentState: .Selected, rightSegmentState: .Highlighted, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlBothSelected"), forLeftSegmentState: .Selected, rightSegmentState: .Selected, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlBothSelected"), forLeftSegmentState: .Highlighted, rightSegmentState: .Selected, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlBothSelected"), forLeftSegmentState: .Highlighted, rightSegmentState: .Highlighted, barMetrics: .Default)
    self.setDividerImage(UIImage(named: "SegmentedControlLeftSelected"), forLeftSegmentState: .Highlighted, rightSegmentState: .Normal, barMetrics: .Default)


    // Set background images
    var normalBackgroundImage = UIImage(named: "SegmentedControlNormal")
    self.setBackgroundImage(normalBackgroundImage, forState: .Normal, barMetrics: .Default)

    var selectedBackgroundImage = UIImage(named: "SegmentedControlSelected");
    self.setBackgroundImage(selectedBackgroundImage, forState: .Selected, barMetrics: .Default)
    self.setBackgroundImage(selectedBackgroundImage, forState: .Highlighted, barMetrics: .Default)
    self.setBackgroundImage(selectedBackgroundImage, forState: .Disabled, barMetrics: .Default)
    self.setBackgroundImage(selectedBackgroundImage, forState: .Application, barMetrics: .Default)
    self.setBackgroundImage(selectedBackgroundImage, forState: .Reserved, barMetrics: .Default)

回答1:

The are some new status which should be handled now:

//The highlighted button can be still unselected
[self.mySegmentedControl setBackgroundImage:unselectedBackgroundImage
                                   forState:UIControlStateHighlighted
                                 barMetrics:UIBarMetricsDefault];

//The alredy selected button is stil selected when it is highlighted
[self.mySegmentedControl setBackgroundImage:selectedBackgroundImage
                                   forState:UIControlStateHighlighted|UIControlStateSelected
                                 barMetrics:UIBarMetricsDefault];


//Handle when the right segment is highlighted but the left is selected
[self.mySegmentedControl setDividerImage:leftSelectedImage
                       forLeftSegmentState:UIControlStateSelected
                       rightSegmentState:UIControlStateHighlighted
                              barMetrics:UIBarMetricsDefault];

//Handle when the right segment is already selected and just highlighted and the right is normal
[self.mySegmentedControl setDividerImage:leftSelectedImage
                     forLeftSegmentState:UIControlStateHighlighted|UIControlStateSelected
                       rightSegmentState:UIControlStateNormal
                              barMetrics:UIBarMetricsDefault];

//Handle when the left segment is highlighted but the right is selected    
[self.mySegmentedControl setDividerImage:rightSelectedImage
                     forLeftSegmentState:UIControlStateHighlighted
                       rightSegmentState:UIControlStateSelected
                              barMetrics:UIBarMetricsDefault];

//Handle when the left segment is already selected and just highlighted and the left is normal
[self.mySegmentedControl setDividerImage:rightSelectedImage
                     forLeftSegmentState:UIControlStateNormal
                       rightSegmentState:UIControlStateHighlighted|UIControlStateSelected
                              barMetrics:UIBarMetricsDefault];

And it seems, that the devider image width is an important thing now. It has effect to the content label width and position. So the devider image should be as shrink as it can.