Ios 将带宽度的边框添加到UIView可在外部显示小背景

Ios 将带宽度的边框添加到UIView可在外部显示小背景,ios,swift,uiview,uikit,xib,Ios,Swift,Uiview,Uikit,Xib,我试图将圆形边框添加到绿色背景的UIView中,我创建了带有borderWidth、cornerRadius和borderColor属性的简单UIView子类,并从情节提要进行设置 @IBDesignable class RoundedView: UIView { @IBInspectable var cornerRadius: CGFloat { get { return layer.cornerRadius }

我试图将圆形边框添加到绿色背景的
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和白色背景上看到外部的绿色边框


你能告诉我怎么了吗?

你现在做的是依靠图层来绘制边界和圆角。所以你不是结果的负责人。你给它一个绿色的背景,现在你看到的背景“突出”在边界的边缘。在任何情况下,拐弯都是一种非常卑鄙和不可靠的圆视图制作方法。要创建圆形视图,请创建圆形遮罩

因此,制作徽章的方法是完全控制它的绘制内容:在白色背景的中心绘制一个绿色圆圈,然后用一个更大的圆圈遮住它以形成边框

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

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)

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

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

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)
let gradientLayer=CAGradientLayer()
//定义颜色
gradientLayer.colors=[>>,]
//将颜色的位置定义为介于0.0到1.0之间的数字
gradientLayer.locations=[0.0,0.7]
//定义框架
gradientLayer.frame=self.classView.bounds
self.classView.layer.insertSublayer(gradientLayer,at:0)

我通过使用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)

一个更简单的修复方法可能是这样屏蔽它:

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

(1) 您没有包含任何关于UIImageView如何在UIView中定位的代码或解释,也没有包含任何约束。(2) 你提到了IB和compile,但是你实际运行应用程序的时间呢?我看到了视图本身的所有正确的东西(代码和IB屏幕截图)。。。如果UIImageView没有边框(并且背景清晰),你应该会很好。(1)更新了我的答案,这个绿点是带有边框的圆点视图,它有一个奇怪的边框问题-它刚好位于
UIImageView
(2)当然,编译和运行-这个边界在模拟器和真实设备中都可见,非常感谢。你能解释一下为什么这是一种“卑鄙且不可靠的方式”吗?另外,你知道为什么会出现绿色边框吗?我已经给你指明了正确的方向。它起作用了,它解决了你提出的问题。试试看。是的,很好,谢谢。我只是想知道边界发生的原因你不需要理由。我解释说,通过让图层为您绘制图形,您可以放手,接受它所做的一切。所以它所做的就是它所做的——如果你选择走这条路的话。解决办法是:不要那样做。你自己画吧。我甚至向你展示了如何做。我不是OP。我主要是评论你因为好奇而拍打OP。你似乎认为他的评论是在和你争论。不管他是不是(我没有这样读),我认为最初问题的原因也很有趣。如果答案是“这是一个私有实现,所以我们不知道它是如何工作的”,那就好了。但OP最初的评论是问我认为好的后续问题,而不是以任何方式质疑你的答案。(我目前正在实施您的答案,谢谢。)