向 UISegmentedControl 添加自定义边框

Adding custom border to UISegmentControl

我正在尝试自定义我的分段控件,如下图所示。所以,到目前为止,我能够自定义其文本属性和颜色。唯一的问题是边界。根据下图,如果选择了我的第一段,则边框应应用于第一段的顶部、右侧和第二段的底部。如果选择了我的第二段,它应该是相反的,即第二段顶部、左侧和第一段底部。

Segment Model Image

到目前为止完成的事情

UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.blue], for: .selected)

UISegmentedControl.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.green], for: .normal)

您可以通过向 UISegmentedControl 添加扩展名来实现。试试这个。

 extension UISegmentedControl {


  private func defaultConfiguration(font: UIFont = UIFont.boldSystemFont(ofSize: 12), color: UIColor = UIColor.gray) {
        let defaultAttributes = [
            NSAttributedStringKey.font.rawValue: font,
            NSAttributedStringKey.foregroundColor.rawValue: color
        ]
        setTitleTextAttributes(defaultAttributes, for: .normal)
    }

   private func selectedConfiguration(font: UIFont = UIFont.boldSystemFont(ofSize: 12), color: UIColor = UIColor.blue) {
        let selectedAttributes = [
            NSAttributedStringKey.font.rawValue: font,
            NSAttributedStringKey.foregroundColor.rawValue: color
        ]
        setTitleTextAttributes(selectedAttributes, for: .selected)
    }


   private func removeBorder(){

        let backgroundImage = getColoredRectImageWith(color: UIColor.white.cgColor, andSize: CGSize(width: self.bounds.size.width, height: self.bounds.size.height), yOffset: 2)  
        let backgroundImage2 = getColoredRectImageWith(color: UIColor.lightGray.cgColor, andSize: CGSize(width: self.bounds.size.width, height: self.bounds.size.height))

        self.setBackgroundImage(backgroundImage2, for: .normal, barMetrics: .default)
        self.setBackgroundImage(backgroundImage, for: .selected, barMetrics: .default)
        self.setBackgroundImage(backgroundImage, for: .highlighted, barMetrics: .default)

        let deviderImage = getColoredRectImageWith(color: UIColor.gray.cgColor, andSize: CGSize(width: 1.0, height: self.bounds.size.height))
        self.setDividerImage(deviderImage, forLeftSegmentState: .selected, rightSegmentState: .normal, barMetrics: .default)

        defaultConfiguration( color: UIColor.green)
        selectedConfiguration(color: UIColor.blue)

    }

    func addUnderlineForSelectedSegment(){
        removeBorder()
        let underlineWidth: CGFloat = self.bounds.size.width / CGFloat(self.numberOfSegments)
        let underlineHeight: CGFloat = 1.0
        let underlineXPosition = CGFloat(selectedSegmentIndex * Int(underlineWidth))
        let underLineYPosition = self.bounds.size.height - 2.0
        let underlineFrame = CGRect(x: underlineXPosition, y: underLineYPosition, width: underlineWidth, height: underlineHeight)

        let topUnderline = UIView(frame: underlineFrame)
        topUnderline.backgroundColor = UIColor.gray
        topUnderline.tag = 1
        topUnderline.frame.origin.y = self.frame.origin.y
        self.addSubview(topUnderline)

        let bottomUnderline = UIView(frame: underlineFrame)
        bottomUnderline.backgroundColor = UIColor.gray
        bottomUnderline.tag = 2
        bottomUnderline.frame.origin.x = topUnderline.frame.maxX
        self.addSubview(bottomUnderline)
    }

    func changeUnderlinePosition(){


        guard let topUnderline = self.viewWithTag(1) else {return}
        let topUnderlineFinalXPosition = (self.bounds.width / CGFloat(self.numberOfSegments)) * CGFloat(selectedSegmentIndex)
        topUnderline.frame.origin.x = topUnderlineFinalXPosition

        guard let bottomUnderline = self.viewWithTag(2) else {return}
        let underlineFinalXPosition = (selectedSegmentIndex == 0) ? topUnderline.frame.maxX : self.frame.origin.x
        bottomUnderline.frame.origin.x = underlineFinalXPosition

    }

    private func getColoredRectImageWith(color: CGColor, andSize size: CGSize,yOffset:CGFloat = 0, hOffset:CGFloat = 0) -> UIImage{
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        let graphicsContext = UIGraphicsGetCurrentContext()
        graphicsContext?.setFillColor(color)
        let rectangle = CGRect(x: 0.0, y: 0.0 + yOffset, width: size.width, height: size.height - hOffset)
        graphicsContext?.fill(rectangle)
        let rectangleImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return rectangleImage!
    }

}

用法

viewDidLoad中添加

mySegmentControl.addUnderlineForSelectedSegment()

并在您的段控制操作中使用

@IBAction func mySegmentControl(_ sender: UISegmentedControl) {

        mySegmentControl.changeUnderlinePosition()
    }