SelectedTintColor of Segment Control is not rounded corner on iOS 13

家住魔仙堡 提交于 2021-02-06 09:22:50

问题


Rounded corner is working great on iOS 12 and below, but it's broken on iOS 13. I've created a custom Segment control class.

Code:

class SegmentedControl: UISegmentedControl {
    override func layoutSubviews() {
      super.layoutSubviews()
      layer.cornerRadius = self.bounds.size.height / 2.0
      layer.borderColor = UIColor(red: 170.0/255.0, green: 170.0/255.0, blue: 170.0/255.0, alpha: 1.0).cgColor
      layer.borderWidth = 1.0
      layer.masksToBounds = true
      clipsToBounds = true

   }
}

I've gone through this post - How to change the colors of a segment in a UISegmentedControl in iOS 13? but I couldn't get any solution.

Screenshot:


回答1:


I was facing the same issue on iOS 13. Then I dug into its view hierarchy then I found it has multiple subviews. So I made a trick for iOS 13. You have to do following changes for iOS 13 -

  1. ChangeselectedSegmentTintColor to Clear - self.selectedSegmentTintColor = .clear
  2. Add following code snippet inside layoutSubviews -

    for i in 0...subviews.count - 1{
    
            if let subview = subviews[i] as? UIImageView{
    
                if i == self.selectedSegmentIndex {
    
                    subview.backgroundColor = UIColor(red: 170.0/255.0, green: 170.0/255.0, blue: 170.0/255.0, alpha: 1.0)
    
                }else{
    
                    subview.backgroundColor = .clear
                }
    
            }
        }
    

I hope it will help you.




回答2:


Swift 5

If you use a subclass:

override func layoutSubviews() {
    super.layoutSubviews()
    roundCorners(radius: frame.height / 2)

    if #available(iOS 13.0, *) {
        selectedSegmentTintColor = .clear
    } else {
        tintColor = .clear
    }

    for (index, subview) in subviews.enumerated() {
        if ((subviews[index] as? UIImageView) != nil) && index == selectedSegmentIndex {
            subview.backgroundColor = .white
            subview.roundCorners(radius: subview.frame.height / 2)
        } else {
            subview.backgroundColor = .clear
        }
    }
}

private func roundCorners(radius: CGFloat) {
    layer.roundCorners(radius: radius)
    self.clipsToBounds = true
}

If you use the default segmented control, you just prefix with name of your segmented control:

mySegmentedControl.selectedSegmentTintColor = .clear

for (index, subview) in mySegmentedControl.subviews.enumerated() {
   .....
}



回答3:


Make a custom class for segment

class CustomSegmentedControl: UISegmentedControl {
override func layoutSubviews() {
    super.layoutSubviews()
    layer.cornerRadius = self.bounds.size.height / 2.0
    layer.borderColor = use_your_custom_color
    layer.borderWidth = 1.0
    layer.masksToBounds = true
    clipsToBounds = true
    for i in 0...subviews.count - 1{
        if let subview = subviews[i] as? UIImageView{
            if i == self.selectedSegmentIndex {
                subview.backgroundColor = use_your_custom_color
            }else{
                subview.backgroundColor = .white
            }
        }
    }
}}

May be this will easy to use like this

   @IBOutlet weak var reminderSegmentControl: CustomSegmentedControl!



回答4:


Similar to other solution I have Following Sub-Class Segment control UISegmentedControl

Which gives following result -

class OYSegmentControl: UISegmentedControl {
  
  override func layoutSubviews(){
    super.layoutSubviews()
    
    let segmentStringSelected: [NSAttributedString.Key : Any] = [
      NSAttributedString.Key.font : UIFont.fontActionLabel(ofSize: 14.0),
      NSAttributedString.Key.foregroundColor : UIColor.white
    ]
    
    let segmentStringHighlited: [NSAttributedString.Key : Any] = [
      NSAttributedString.Key.font : UIFont.fontActionLabel(ofSize: 14.0),
      NSAttributedString.Key.foregroundColor : #colorLiteral(red: 0.5567105412, green: 0.5807551742, blue: 0.6022000909, alpha: 1)
    ]
    
    setTitleTextAttributes(segmentStringHighlited, for: .normal)
    setTitleTextAttributes(segmentStringSelected, for: .selected)
    setTitleTextAttributes(segmentStringHighlited, for: .highlighted)
    
    layer.masksToBounds = true
    
    if #available(iOS 13.0, *) {
      selectedSegmentTintColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
    } else {
      tintColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
    }
    
    backgroundColor = #colorLiteral(red: 0.9191747308, green: 0.9334954619, blue: 0.9506797194, alpha: 1)
    
    //corner radius
    let cornerRadius = bounds.height / 2
    let maskedCorners: CACornerMask = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner]
    //background
    clipsToBounds = true
    layer.cornerRadius = cornerRadius
    layer.maskedCorners = maskedCorners

    let foregroundIndex = numberOfSegments
    if subviews.indices.contains(foregroundIndex),
      let foregroundImageView = subviews[foregroundIndex] as? UIImageView {
      foregroundImageView.image = UIImage()
      foregroundImageView.clipsToBounds = true
      foregroundImageView.layer.masksToBounds = true
      foregroundImageView.backgroundColor = #colorLiteral(red: 0, green: 0.861200273, blue: 0.67304039, alpha: 1)
      
      foregroundImageView.layer.cornerRadius = bounds.height / 2 + 5
      foregroundImageView.layer.maskedCorners = maskedCorners
    }
  }
  
  override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return false
  }
  
}

Language: Swift 5.1

NOTE: This only works if you have outlet / frame set from Storyboard. Frame from code will cause issues. The extra 5 px on cornerRadius,a hack to make it better round rect. I ended up using - https://github.com/alokc83/MASegmentedControl as my use-case was from Code only view.




回答5:


this code works for me iOS 13 - Swift 5.1

    segment.layer.cornerRadius = 12
    segment.layer.borderWidth = 1
    segment.layer.borderColor = UIColor.black.cgColor
    segment.font(name: "TheSans-Plain", size: 14)
    segment.clipsToBounds = true
    segment.layer.masksToBounds = true

    if #available(iOS 13.0, *) {
        segment.selectedSegmentTintColor = .red
    } 


来源:https://stackoverflow.com/questions/58315497/selectedtintcolor-of-segment-control-is-not-rounded-corner-on-ios-13

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!