【问题标题】:Adding border with width to UIView show small background outside向 UIView 添加带宽度的边框在外面显示小背景
【发布时间】:2017-04-19 07:22:00
【问题描述】:

我正在尝试将圆形边框添加到具有绿色背景的UIView,我创建了具有borderWidth、cornerRadius 和borderColor 属性的简单UIView 子类,并且我正在从情节提要中设置它。

@IBDesignable
class RoundedView: UIView {

    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }

    @IBInspectable var borderColor: UIColor {
        get {
            if let color = layer.borderColor {
                return UIColor(cgColor: color)
            } else {
                return UIColor.clear
            }
        }
        set {
            layer.borderColor = newValue.cgColor
        }
    } 

}

但是当我编译并运行一个应用程序或在 InterfaceBuilder 中显示它时,我可以看到边界外的一条线仍然存在(并且在白色背景上非常明显)。

这个RoundedView,绿色背景,框架10x10,圆角半径= 5 放置在平原UIImageView 的一角(指示某人是否在线)。您可以在 UIImageView 和白色背景上看到外面的绿色边框。

你能告诉我有什么问题吗?

【问题讨论】:

  • (1) 您没有包含任何代码或说明 UIImageView 如何在 UIView 内定位或任何约束。 (2) 你提到了 IB 和 compile,但是你实际运行应用程序的时候呢?我看到了视图本身的所有正确的东西(代码和你的 IB 截图)......如果 UIImageView 没有边框(和清晰的背景)你应该很好。
  • (1) 更新了我的答案,这个绿点是带边框的RoundedView,它有这个奇怪的边框问题——它只是放在UIImageView 上(2) 当然,编译并运行——这个在绿点周围的模拟器和真实设备中都可以看到边框

标签: ios swift uiview uikit xib


【解决方案1】:

您正在做的是依靠图层来绘制边框和圆角。所以你不负责结果。你给它一个绿色背景,现在你看到背景“突出”在边框的边缘。无论如何,圆角是一种非常不可靠且不可靠的方式来制作圆形视图。要制作圆形视图,请制作圆形 蒙版

因此,制作徽章的方法是完全掌控它所绘制的内容:白色的中心画一个绿色圆圈 背景,遮罩 用一个更大的圆圈来做边框。

这是一个徽章视图,可以精确地完成您所追求的工作,外部没有人工制品:

class Badge : UIView {
    class Mask : UIView {
        override init(frame:CGRect) {
            super.init(frame:frame)
            self.isOpaque = false
            self.backgroundColor = .clear
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        override func draw(_ rect: CGRect) {
            let con = UIGraphicsGetCurrentContext()!
            con.fillEllipse(in: CGRect(origin:.zero, size:rect.size))
        }
    }
    let innerColor : UIColor
    let outerColor : UIColor
    let innerRadius : CGFloat
    var madeMask = false
    init(frame:CGRect, innerColor:UIColor, outerColor:UIColor, innerRadius:CGFloat) {
        self.innerColor = innerColor
        self.outerColor = outerColor
        self.innerRadius = innerRadius
        super.init(frame:frame)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func draw(_ rect: CGRect) {
        let con = UIGraphicsGetCurrentContext()!
        con.setFillColor(outerColor.cgColor)
        con.fill(rect)
        con.setFillColor(innerColor.cgColor)
        con.fillEllipse(in: CGRect(
            x: rect.midX-innerRadius, y: rect.midY-innerRadius,
            width: 2*innerRadius, height: 2*innerRadius))
        if !self.madeMask {
            self.madeMask = true // do only once
            self.mask = Mask(frame:CGRect(origin:.zero, size:rect.size))
        }
    }
}

我尝试了如下示例设置:

let v = Badge(frame: CGRect(x:100, y:100, width:16, height:16), 
              innerColor: .green, outerColor: .white, innerRadius: 5)
self.view.addSubview(v)

看起来不错。根据需要调整参数。

【讨论】:

  • 非常感谢。你能解释一下为什么这是“令人讨厌和不可靠的方式”吗?另外,你知道为什么会出现这个绿色边框吗?
  • 我已经向您展示了正确的方法。它有效,它解决了你提出的问题。试试看。
  • 是的,太好了,谢谢。我只是想知道这个边界出现的原因
  • 你不需要理由。我解释说,通过要求图层为您进行绘图,您将把手放开并接受它所做的任何事情。所以它所做的就是它所做的——如果这是你选择走的路。解决方案是:不要那样做。自己画吧。我什至向你展示了如何。
  • 我不是 OP。我主要是评论你因为好奇而拍下OP。你似乎把他的评论当作和你争论。不管他是不是(而且我不是那样读的),认为原始问题的why也很有趣.如果答案是“这是一个私有实现,所以我们不知道它是如何工作的”,那么很好。但是 OP 的最初评论是询问我认为很好的后续问题,而不以任何方式挑战您的答案。 (我目前正在实施你的答案,所以谢谢。)
【解决方案2】:

我通过使用 UIBezierPath 并添加到视图层解决了这个问题:

        let strokePath = UIBezierPath(roundedRect: view.bounds, cornerRadius: view.frame.width / 2)
        let stroke = CAShapeLayer()
        stroke.frame = bounds
        stroke.path = strokePath.cgPath
        stroke.fillColor = .green.cgColor
        stroke.lineWidth = 1.0
        stroke.strokeColor = .white.cgColor
        view.layer.insertSublayer(stroke, at: 2)

【讨论】:

    【解决方案3】:

    我用渐变解决了这个问题。 只需将圆圈的背景颜色设置为渐变即可。

    let gradientLayer = CAGradientLayer()
        //define colors
        gradientLayer.colors = [<<your_bgc_color>>>>,  <<border__bgc__color>>]
        //define locations of colors as NSNumbers in range from 0.0 to 1.0
        gradientLayer.locations = [0.0, 0.7]
        //define frame
        gradientLayer.frame = self.classView.bounds
    
        self.classView.layer.insertSublayer(gradientLayer, at: 0)
    

    MyImage

    【讨论】:

      【解决方案4】:

      更简单的解决方法可能是像这样掩盖它:

      let mask = UIView()
      mask.backgroundColor = .black
      mask.frame = yourCircleView.bounds.inset(by: UIEdgeInsets(top: 0.1, left: 0.1, bottom: 0.1, right: 0.1))
      mask.layer.cornerRadius = mask.height * 0.5
      yourCircleView.mask = mask
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-26
        • 2014-08-04
        相关资源
        最近更新 更多