Если добавить границу представления с помощью кода в представлении, например
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
граница добавляется внутри вида, как показано ниже:
правый вид - это исходный вид, как вы можете видеть, черная область окна с рамкой меньше исходного. но то , что я хочу , чтобы это граница за пределы первоначальной точки зрения, как это: . черная область равна исходной, как это реализовать?
Хорошо, уже есть принятый ответ, но я думаю, что есть лучший способ сделать это, вам просто нужно создать новый слой немного больше, чем ваше представление, и не маскировать его до границ слоя представления (что на самом деле поведение по умолчанию). Вот пример кода:
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
и рамку слоя. Это лучше, чем использование второго вида, немного большего размера, поскольку aCALayer
легче, чем a,UIView
и вам не нужно изменять рамкуmyView
, что хорошо, например, еслиmyView
этоUIImageView
NB: Для меня результат был не идеальным на симуляторе (слой был не совсем в правильном положении, поэтому слой иногда был толще с одной стороны), но был именно тем, что требуется на реальном устройстве.
РЕДАКТИРОВАТЬ
На самом деле проблема, о которой я говорю в NB, заключалась только в том, что я уменьшил экран симулятора, при нормальном размере проблем нет.
Надеюсь, поможет
источник
С принятым выше лучшим ответом я испытал такие неприятные результаты и неприглядные края:
Итак, я поделюсь с вами своим расширением 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 }
источник
Как я разместил рамку вокруг своего представления пользовательского интерфейса (основное - SubscriptionAd) в раскадровке, - это поместить его в другое представление пользовательского интерфейса (фон - BackgroundAd). Фон UIView имеет цвет фона, который соответствует желаемому цвету границы, а основной UIView имеет значение ограничения 2 с каждой стороны.
Я свяжу фоновое представление со своим ViewController, а затем включу и выключу границу, изменив цвет фона.
источник
Swift 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() } }
источник