如果使用类似视图的代码在视图中添加边框
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
将边框添加到视图内部,如下所示:
如您所见,右边的视图是原始视图,带边框的视图的黑色区域小于原始视图。但我想得到的是原始视图之外的边框,如下所示:。黑色区域等于原始区域,我该如何实施?
Answers:
不幸的是,您不仅可以设置将边框与外部对齐的小属性。它以与内部对齐的方式进行绘制,因为UIViews默认绘制操作在其范围内进行绘制。
想到的最简单的解决方案是在应用边框时通过边框宽度的大小扩展UIView:
CGFloat borderWidth = 2.0f;
self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth);
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = borderWidth;
好的,已经有一个可以接受的答案,但是我认为有一种更好的方法,您只需要拥有一个比视图大一点的新层,并且不必将其蒙版到视图层的边界即可(实际上是默认行为)。这是示例代码:
CALayer * externalBorder = [CALayer layer];
externalBorder.frame = CGRectMake(-1, -1, myView.frame.size.width+2, myView.frame.size.height+2);
externalBorder.borderColor = [UIColor blackColor].CGColor;
externalBorder.borderWidth = 1.0;
[myView.layer addSublayer:externalBorder];
myView.layer.masksToBounds = NO;
当然,这是如果您希望边框为1个单位大,如果您希望更大,则可以相应地调整borderWidth
图层的和。这比使用第二个视图更好,因为第二个视图CALayer
要比a小一些,UIView
并且您不必修改的框架myView
,例如,如果myView
是UIImageView
注意:对我来说,结果在模拟器上并不完美(该层的位置不正确,因此该层的一侧有时更厚),但这恰恰是实际设备上所要求的。
编辑
实际上,我在笔记本电脑中谈论的问题仅仅是因为我缩小了模拟器的屏幕,在正常尺寸下绝对没有问题
希望能帮助到你
通过以上公认的最佳答案,我获得了不好的结果和难看的优势:
因此,我将与您分享我的UIView Swift扩展,它使用UIBezierPath代替边框轮廓-没有难看的边缘(受@Fattie启发):
// UIView+BezierPathBorder.swift
import UIKit
extension UIView {
fileprivate var bezierPathIdentifier:String { return "bezierPathBorderLayer" }
fileprivate var bezierPathBorder:CAShapeLayer? {
return (self.layer.sublayers?.filter({ (layer) -> Bool in
return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil
}) as? [CAShapeLayer])?.first
}
func bezierPathBorder(_ color:UIColor = .white, width:CGFloat = 1) {
var border = self.bezierPathBorder
let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius)
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
if (border == nil) {
border = CAShapeLayer()
border!.name = self.bezierPathIdentifier
self.layer.addSublayer(border!)
}
border!.frame = self.bounds
let pathUsingCorrectInsetIfAny =
UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius)
border!.path = pathUsingCorrectInsetIfAny.cgPath
border!.fillColor = UIColor.clear.cgColor
border!.strokeColor = color.cgColor
border!.lineWidth = width * 2
}
func removeBezierPathBorder() {
self.layer.mask = nil
self.bezierPathBorder?.removeFromSuperlayer()
}
}
例:
let view = UIView(frame: CGRect(x: 20, y: 20, width: 100, height: 100))
view.layer.cornerRadius = view.frame.width / 2
view.backgroundColor = .red
//add white 2 pixel border outline
view.bezierPathBorder(.white, width: 2)
//remove border outline (optional)
view.removeBezierPathBorder()
对于Swift实施,您可以将其添加为UIView扩展。
extension UIView {
struct Constants {
static let ExternalBorderName = "externalBorder"
}
func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.whiteColor()) -> CALayer {
let externalBorder = CALayer()
externalBorder.frame = CGRectMake(-borderWidth, -borderWidth, frame.size.width + 2 * borderWidth, frame.size.height + 2 * borderWidth)
externalBorder.borderColor = borderColor.CGColor
externalBorder.borderWidth = borderWidth
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, atIndex: 0)
layer.masksToBounds = false
return externalBorder
}
func removeExternalBorders() {
layer.sublayers?.filter() { $0.name == Constants.ExternalBorderName }.forEach() {
$0.removeFromSuperlayer()
}
}
func removeExternalBorder(externalBorder: CALayer) {
guard externalBorder.name == Constants.ExternalBorderName else { return }
externalBorder.removeFromSuperlayer()
}
}
那么没有直接的方法可以执行此操作。您可以考虑一些解决方法。
如果您不需要确定的边界(明晰边界),则可以依靠阴影来达到目的
[view1 setBackgroundColor:[UIColor blackColor]];
UIColor *color = [UIColor yellowColor];
view1.layer.shadowColor = [color CGColor];
view1.layer.shadowRadius = 10.0f;
view1.layer.shadowOpacity = 1;
view1.layer.shadowOffset = CGSizeZero;
view1.layer.masksToBounds = NO;
在添加边框之前,使用边框宽度增加视图框架的宽度和高度:
float borderWidth = 2.0f
CGRect frame = self.frame;
frame.width += borderWidth;
frame.height += borderWidth;
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
实际上有一个非常简单的解决方案。只需将它们设置如下:
view.layer.borderWidth = 5
view.layer.borderColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5).cgColor
view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.25).cgColor
我喜欢@picciano的解决方案 如果要爆炸圆形而不是正方形,请使用以下命令替换addExternalBorder函数:
func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) {
let externalBorder = CALayer()
externalBorder.frame = CGRect(x: -borderWidth, y: -borderWidth, width: frame.size.width + 2 * borderWidth, height: frame.size.height + 2 * borderWidth)
externalBorder.borderColor = borderColor.cgColor
externalBorder.borderWidth = borderWidth
externalBorder.cornerRadius = (frame.size.width + 2 * borderWidth) / 2
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, at: 0)
layer.masksToBounds = false
}
我喜欢@picciano和@Maksim Kniazev的解决方案。我们还可以使用以下方法创建环形边框:
func addExternalAnnularBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) {
let externalBorder = CALayer()
externalBorder.frame = CGRect(x: -borderWidth*2, y: -borderWidth*2, width: frame.size.width + 4 * borderWidth, height: frame.size.height + 4 * borderWidth)
externalBorder.borderColor = borderColor.cgColor
externalBorder.borderWidth = borderWidth
externalBorder.cornerRadius = (frame.size.width + 4 * borderWidth) / 2
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, at: 0)
layer.masksToBounds = false
}
迅捷5
extension UIView {
fileprivate struct Constants {
static let externalBorderName = "externalBorder"
}
func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) -> CALayer {
let externalBorder = CALayer()
externalBorder.frame = CGRect(x: -borderWidth, y: -borderWidth, width: frame.size.width + 2 * borderWidth, height: frame.size.height + 2 * borderWidth)
externalBorder.borderColor = borderColor.cgColor
externalBorder.borderWidth = borderWidth
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, at: 0)
layer.masksToBounds = false
return externalBorder
}
func removeExternalBorders() {
layer.sublayers?.filter() { $0.name == Constants.externalBorderName }.forEach() {
$0.removeFromSuperlayer()
}
}
func removeExternalBorder(externalBorder: CALayer) {
guard externalBorder.name == Constants.externalBorderName else { return }
externalBorder.removeFromSuperlayer()
}
}