【问题标题】:SelectedTintColor of Segment Control is not rounded corner on iOS 13iOS 13 上 Segment Control 的 SelectedTintColor 不是圆角
【发布时间】:2020-02-07 11:04:03
【问题描述】:

圆角在 iOS 12 及更低版本上运行良好,但在 iOS 13 上出现问题。我创建了一个自定义 Segment 控件类。

代码:

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

   }
}

我已经浏览过这篇文章 - How to change the colors of a segment in a UISegmentedControl in iOS 13? 但我找不到任何解决方案。

截图:

【问题讨论】:

  • UISegmentedControl 基本上不是单一视图。在您的代码中,您将主要的SegmentedControl 舍入,但其中嵌入的视图不受影响。我建议您使用自定义控件或自己设计一个。 UIControl 会帮助你。
  • @user1374 同样的问题,我也试过他的解决方案。
  • @HarvantS.Choudhary UISegmentedControl 在引入时从一开始就包含多个子视图。虽然我会尝试你的建议。谢谢。
  • 是的,但是你没有改变那些孩子的圆角半径,在 iOS 13 苹果改变了段控制的 UI。如果您尝试在 iOS 13 中修圆边缘,它看起来不会很好,并且您会得到类似的结果。与其加倍努力修复两个不同的 UI,不如创建自己的或第三方控件。

标签: ios swift4 uisegmentedcontrol ios13


【解决方案1】:

我在 iOS 13 上遇到了同样的问题。然后我深入研究了它的视图层次结构,然后我发现它有多个子视图。所以我为 iOS 13 做了一个技巧。你必须为 iOS 13 做以下更改 -

  1. selectedSegmentTintColor 更改为Clear - self.selectedSegmentTintColor = .clear
  2. layoutSubviews中添加以下代码sn-p -

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

希望对你有帮助。

【讨论】:

  • 让我看看你的解决方案。
【解决方案2】:

此代码适用于我 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
    } 

【讨论】:

    【解决方案3】:

    为细分创建自定义类

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

    可能会像这样容易使用

       @IBOutlet weak var reminderSegmentControl: CustomSegmentedControl!
    

    【讨论】:

      【解决方案4】:

      斯威夫特 5

      如果您使用子类:

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

      方便方法:

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

      如果您使用默认分段控件,您只需在您的分段控件名称前加上前缀:

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

      【讨论】:

      • 对我来说效果很好,谢谢。请注意:我不认为roundCorners()CALayer 的开箱即用方法。也许您的项目中有一个扩展来声明它?
      【解决方案5】:

      与其他解决方案类似,我有以下子类段控制 UISegmentedControl

      这给出了以下结果 -

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

      语言:Swift 5.1

      注意:仅当您从 Storyboard 设置了插座/框架时,这才有效。 来自代码的框架会导致问题。 cornerRadius 上额外的 5 px,一个 hack 以使其更好地圆形矩形。 我最终使用了 - https://github.com/alokc83/MASegmentedControl,因为我的用例来自仅代码视图。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-17
        • 1970-01-01
        • 2023-03-31
        • 2013-01-08
        相关资源
        最近更新 更多