【问题标题】:How to remove border from segmented control如何从分段控件中删除边框
【发布时间】:2015-10-17 13:45:21
【问题描述】:

如何删除分段控件的外边框? 我已将分隔线图像设置为我想要的,但现在要遵循我的应用程序的模拟,我需要有一个没有外边框的分段控件。

【问题讨论】:

    标签: ios swift uisegmentedcontrol


    【解决方案1】:

    Sohil's answer 确实帮助了我。

    但是如果不设置UIImage的大小,可能会影响UISegmentedControl的大小。

    如果你也遇到这个问题,请考虑使用以下代码。

    func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
        return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
    }
    
    extension UIImage {
        func resized(_ size: CGSize) -> UIImage? {
            defer { UIGraphicsEndImageContext() }
            UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
            self.draw(in: CGRect(origin: .zero, size: size))
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    
        func resized(_ size: CGFloat) -> UIImage? {
            guard size > 0, self.size.width > 0, self.size.height > 0 else { return nil }
            let ratio = size / max(self.size.width, self.size.height)
            return self.resized(self.size * ratio)
        }
    
        func refilled(_ color: UIColor) -> UIImage? {
            defer { UIGraphicsEndImageContext() }
            UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
            color.set()
            UIGraphicsGetCurrentContext()?.fill(CGRect(origin: .zero, size: self.size))
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    
        public convenience init?(color: UIColor = .clear, size: CGSize) {
            defer { UIGraphicsEndImageContext() }
            UIGraphicsBeginImageContext(size)
    
            guard let context = UIGraphicsGetCurrentContext() else { return nil }
            context.setFillColor(color.cgColor);
            context.fill(CGRect(origin: .zero, size: size));
            guard let cgImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else { return nil }
    
            self.init(cgImage: cgImage)
        }
    }
    
    extension UISegmentedControl {
        func removeBorders() {
            let image = UIImage(size: self.bounds.size)
            self.setBackgroundImage(image, for: .normal, barMetrics: .default)
            self.setBackgroundImage(image?.refilled(self.tintColor), for: .selected, barMetrics: .default)
            self.setDividerImage(image?.resized(1), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
        }
    }
    

    易于使用:

    segmentedControl.removeBorders()
    

    【讨论】:

      【解决方案2】:

      您必须了解的是backgroundColor 属性不是有状态的。 因此你必须使用setBackgroundImage(_:for:barMetrics:)。

      我们可以使用以下函数轻松删除边框和分隔线。

      对于 Swift 3 和 4+:

      extension UISegmentedControl {
          func removeBorders() {
              setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
              setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
              setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
          }
      
          // create a 1x1 image with this color
          private func imageWithColor(color: UIColor) -> UIImage {
              let rect = CGRect(x: 0.0, y: 0.0, width:  1.0, height: 1.0)
              UIGraphicsBeginImageContext(rect.size)
              let context = UIGraphicsGetCurrentContext()
              context!.setFillColor(color.cgColor);
              context!.fill(rect);
              let image = UIGraphicsGetImageFromCurrentImageContext();
              UIGraphicsEndImageContext();
              return image!
          }
      }
      

      对于 Swift 2.2:

      extension UISegmentedControl {
          func removeBorders() {
              setBackgroundImage(imageWithColor(backgroundColor!), forState: .Normal, barMetrics: .Default)
              setBackgroundImage(imageWithColor(tintColor!), forState: .Selected, barMetrics: .Default)
              setDividerImage(imageWithColor(UIColor.clearColor()), forLeftSegmentState: .Normal, rightSegmentState: .Normal, barMetrics: .Default)
          }
      
          // create a 1x1 image with this color
          private func imageWithColor(color: UIColor) -> UIImage {
              let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
              UIGraphicsBeginImageContext(rect.size)
              let context = UIGraphicsGetCurrentContext()
              CGContextSetFillColorWithColor(context, color.CGColor);
              CGContextFillRect(context, rect);
              let image = UIGraphicsGetImageFromCurrentImageContext();
              UIGraphicsEndImageContext();
              return image
          }
      }
      

      调用上述函数。

      segmentedControl.removeBorders()
      

      参考:Remove UISegmentedControl separators completely. (iphone)

      感谢https://stackoverflow.com/users/3921490/amagain Swift 3 版本。

      【讨论】:

      • 谢谢 :) 成功了 =D 但是还有一个问题,这会使我的分段控件有一个尖锐的矩形角,有什么方法可以使它变圆吗?
      • @Happiehappie 不可以,请参考这个答案stackoverflow.com/questions/1834244/…
      • 我收到fatal error: unexpectedly found nil while unwrapping an Optional value在线setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
      • 您还需要将背景颜色设置为Default 以外的其他颜色。 backgroundColor 设置为 Default 时为 nil。
      • 修复后台零问题:setBackgroundImage(imageWithColor(color: backgroundColor ?? .white), for: .normal, barMetrics: .default)
      【解决方案3】:

      斯威夫特 5.x:

      此解决方案仅删除外部边框并保留每个按钮上的圆角

      extension UISegmentedControl {
          func removeBorders(andBackground:Bool=false) {
              setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
              setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
              setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
      
              _ = self.subviews.compactMap {
                  if ($0.frame.width>0) {
                      $0.layer.cornerRadius = 8
                      $0.layer.borderColor = UIColor.clear.cgColor
                      $0.clipsToBounds = true
                      $0.layer.borderWidth = andBackground ? 1.0 : 0.0
                      $0.layer.borderColor = andBackground ? tintColor?.cgColor : UIColor.clear.cgColor
                      andBackground ? $0.layer.backgroundColor = UIColor.clear.cgColor : nil
                  }
              }
          }
      
          // create a 1x1 image with this color
          private func imageWithColor(color: UIColor) -> UIImage {
              let rect = CGRect(x: 0.0, y: 0.0, width:  1.0, height: 1.0)
              UIGraphicsBeginImageContext(rect.size)
              let context = UIGraphicsGetCurrentContext()
              context!.setFillColor(color.cgColor);
              context!.fill(rect);
              let image = UIGraphicsGetImageFromCurrentImageContext();
              UIGraphicsEndImageContext();
              return image!
          }
      }
      

      用法:

      mySegmentedControl.removeBorders()
      

      【讨论】:

      • 去除圆角。
      • @RoneySampaio 这个方法的目的是去除外圆角,你看标题和描述了吗?它为内部的每个按钮重新创建圆角..
      【解决方案4】:
      • 接受的答案适用于摆脱边界。
      • here 提到的解决方案也适用于禁用分段控件。

      然而,将这两个解决方案放在一起,我无法在disabled 状态下获得正确的selected 段。

      我想要的是在选择一个段并进行网络调用时,我想禁用分段控件。

      结果是这样的:

      想要的是这样的:

      Sohil's solution 的唯一补充是:

      setBackgroundImage(imageWithColor(color: imageWithColor(color: tintColor)), for: [.selected, .disabled], barMetrics: .default)
      

      在选中&&禁用段之后会有正确的颜色。

      【讨论】:

        【解决方案5】:

        如果您只需要对文本进行分段控制,请使用,

        segmentControl.backgroundColor = .clear
        segmentControl.tintColor = .clear
        
        let attributes: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.white]
        segmentControl.setTitleTextAttributes(attributes, for: .normal)
        
        let selectedAttrib: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.red]
        segmentControl.setTitleTextAttributes(hightLightedStateAttrib, for: .selected)
        

        注意:我用谷歌搜索了很长时间,这就是我在这里发布的原因。

        来源:CodeMentor

        【讨论】:

          【解决方案6】:

          您可能有不想要圆形边框的用例,因为如果它嵌入在单元格中,您不想看到它。在这种情况下,将自动布局约束设置为 -2,边框将被隐藏,因为它将超出单元格边框。

          【讨论】:

            【解决方案7】:

            希望对大家有所帮助

            斯威夫特 - 4

            将 Segment 控件的背景颜色和色调颜色设置为相同的颜色。 然后“设置段控件的 titleTextAttributes”

                segmentedControl.tintColor = UIColor.red
                segmentedControl.backgroundColor = UIColor.red
                let attributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
                segmentedControl.setTitleTextAttributes(attributes, for: .normal)
                segmentedControl.setTitleTextAttributes(attributes, for: .selected)
            

            【讨论】:

            • 如果我想要不同的色调,那它就行不通了。
            • 是的,没错。当 backgroundColor 和 Tint 颜色相同时,这是一种技巧,然后 borderColor 将与 TintColor 相同。
            【解决方案8】:

            如果你想保存单元格之间的边框

            extension UISegmentedControl {
              func removeBorders() {
                if let backgroundColor = backgroundColor, let backgroundImage = UIImage.imageWithSize(size: CGSize.one_one, color: backgroundColor){
                  setBackgroundImage(backgroundImage, for: .normal, barMetrics: .default)
                }
            
                if let tintColor = tintColor, let tintImage = UIImage.imageWithSize(size: CGSize.one_one, color: tintColor){
                  setBackgroundImage(tintImage, for: .selected, barMetrics: .default)
                    setDividerImage(tintImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
                }
              }
            }
            
            extension CGSize{
              static var one_one: CGSize{
                return CGSize(width: 1.0, height: 1.0)
              }
            }
            
            extension UIImage{
              static func imageWithSize(size : CGSize, color : UIColor = UIColor.white) -> UIImage? {
                var image:UIImage? = nil
                UIGraphicsBeginImageContext(size)
                if let context = UIGraphicsGetCurrentContext() {
                  context.setFillColor(color.cgColor)
                  context.addRect(CGRect(origin: CGPoint.zero, size: size));
                  context.drawPath(using: .fill)
                  image = UIGraphicsGetImageFromCurrentImageContext();
                }
                UIGraphicsEndImageContext()
                return image
              }
            }
            

            【讨论】:

              【解决方案9】:

              这是Sohil 的答案的 swift 3 版本,可能对其他人有所帮助。它确实帮助了我。 :)

              extension UISegmentedControl {
              func removeBorders() {
                  setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
                  setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
                  setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
              }
              
              // create a 1x1 image with this color
              private func imageWithColor(color: UIColor) -> UIImage {
                  let rect = CGRect(x: 0.0, y: 0.0, width:  1.0, height: 1.0)
                  UIGraphicsBeginImageContext(rect.size)
                  let context = UIGraphicsGetCurrentContext()
                  context!.setFillColor(color.cgColor);
                  context!.fill(rect);
                  let image = UIGraphicsGetImageFromCurrentImageContext();
                  UIGraphicsEndImageContext();
                  return image!
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 2014-12-15
                • 1970-01-01
                • 2011-07-11
                • 1970-01-01
                • 1970-01-01
                • 2011-02-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多