Добавьте границу вне UIView (вместо внутренней)
Если добавить границу представления с использованием кода в виде, подобном
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
граница добавляется внутри представления, как показано ниже:
![enter image description here]()
правый вид - это исходное представление, как вы можете видеть, черная область граничного вида меньше оригинальной. но то, что я хочу получить, является границей вне исходного вида, например:
. черная область равна оригинальной, как я могу ее реализовать?
Ответы
Ответ 1
К сожалению, есть не просто небольшое свойство, которое вы можете установить для выравнивания границы с внешним. Он выровняется по внутренней стороне, потому что операции рисования по умолчанию UIViews рисуют в пределах своих границ.
Самое простое решение, которое приходит на ум, состоит в том, чтобы расширить UIView на размер ширины границы при применении границы:
CGFloat borderWidth = 2.0f;
self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth);
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = borderWidth;
Ответ 2
Хорошо, уже есть принятый ответ, но я думаю, что есть лучший способ сделать это, вы просто должны иметь новый слой немного больше, чем ваш взгляд, и не замаскировать его до границ уровня представления ( который фактически является поведением по умолчанию). Вот пример кода:
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;
Конечно, если вы хотите, чтобы ваша граница была на единицу больше, если вы хотите больше адаптировать borderWidth
и кадр слоя соответственно.
Это лучше, чем использование второго представления, которое немного больше, поскольку CALayer
легче, чем UIView
, и вам не нужно изменять кадр myView
, что хорошо, например, если myView
является UIImageView
NB: Для меня результат был не идеальным на симуляторе (слой не был точно в правильном положении, так что слой был толще с одной стороны иногда), но это именно то, что требуется на реальном устройство.
EDIT
На самом деле проблема, о которой я говорю в N.B, была только потому, что я уменьшил экран симулятора, при нормальном размере проблем нет.
Надеюсь, что это поможет
Ответ 3
Ну нет прямого метода для этого
Вы можете рассмотреть некоторые обходные пути.
- Измените и увеличьте рамку и добавьте bordercolor, как и вы.
- Добавить представление за текущим представлением с большим размером, чтобы оно отображалось как border.Can можно было выполнять как пользовательский класс представления
-
Если вам не нужна определенная граница (прозрачная граница), вы можете зависеть от тени для цели
[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;
Ответ 4
Получив лучший ответ, я получил опыт с такими не очень хорошими результатами и неприглядными краями:
![border without bezier path]()
Итак, я поделюсь с вами своим расширением UIView Swift, которое вместо UIBezierPath используется в качестве контура границы - без неприглядных краев (вдохновлено @Fattie):
![border with bezier path]()
// 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()
Ответ 5
Для реализации 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()
}
}
Ответ 6
Увеличьте ширину и высоту рамки представления с шириной границы перед добавлением границы:
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;
Ответ 7
Мне понравилось решение @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
}
Ответ 8
Мне понравилось решение @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, ширина: кадр. size.width + 4 * borderWidth, высота: 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
}