Jeśli dodasz obramowanie widoku za pomocą kodu w widoku, takim jak
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
obramowanie jest dodawane wewnątrz widoku w następujący sposób:
widok właściwy jest widokiem oryginalnym, jak widać, czarny obszar widoku granicznego jest mniejszy niż widok oryginalny. ale to, co chcę dostać to poza granicę oryginalnego widoku, tak: . czarny obszar jest taki sam jak oryginalny, jak mogę to zaimplementować?
Ok, jest już zaakceptowana odpowiedź, ale myślę, że jest lepszy sposób, aby to zrobić, wystarczy mieć nową warstwę nieco większą niż twój widok i nie maskować jej do granic warstwy widoku (która w rzeczywistości jest zachowanie domyślne). Oto przykładowy kod:
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;
Oczywiście dzieje się tak, jeśli chcesz, aby obramowanie było duże o 1 jednostkę, jeśli chcesz więcej, odpowiednio dostosuj
borderWidth
ramkę warstwy i ramkę. Jest to lepsze niż użycie drugiego widoku nieco większego, ponieważ aCALayer
jest lżejsze niż aUIView
i nie musisz modyfikować ramkimyView
, co jest dobre, na przykład, jeślimyView
jestUIImageView
NB: Dla mnie wynik nie był doskonały na symulatorze (warstwa nie była dokładnie we właściwej pozycji, więc czasami warstwa była grubsza z jednej strony), ale był dokładnie tym, o co proszono na prawdziwym urządzeniu.
EDYTOWAĆ
Właściwie problem o którym mówię w NB był tylko dlatego, że zmniejszyłem ekran symulatora, przy normalnym rozmiarze absolutnie nie ma problemu
Mam nadzieję, że to pomoże
źródło
Dzięki powyższej akceptowanej najlepszej odpowiedzi doświadczyłem takich niezbyt ładnych wyników i brzydkich krawędzi:
Więc podzielę się z Tobą moim rozszerzeniem UIView Swift , które zamiast tego używa UIBezierPath jako konturu obramowania - bez brzydkich krawędzi (zainspirowane @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() } }
Przykład:
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()
źródło
W przypadku implementacji Swift możesz dodać to jako rozszerzenie 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() } }
źródło
Cóż, nie ma na to bezpośredniej metody.Możesz rozważyć kilka obejść.
Jeśli nie potrzebujesz określonej ramki (wyraźnej granicy), możesz polegać na cieniu do tego celu
[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;
źródło
Przed dodaniem obramowania zwiększ szerokość i wysokość ramki widoku o szerokość obramowania:
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;
źródło
W rzeczywistości istnieje bardzo proste rozwiązanie. Po prostu ustaw je w ten sposób:
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
źródło
Podobało mi się rozwiązanie @picciano Jeśli chcesz eksplodować koło zamiast kwadratu, zamień funkcję addExternalBorder na :
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 }
źródło
Podobało mi się rozwiązanie @picciano & @Maksim Kniazev. Możemy również utworzyć obramowanie pierścieniowe z:
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 }
źródło
Jak umieściłem obramowanie wokół mojego widoku interfejsu użytkownika (główny - reklama subskrypcyjna) w Storyboard, to umieszczenie go w innym widoku interfejsu użytkownika (tło - reklama w tle). Tło UIView ma kolor tła, który odpowiada żądanemu kolorowi obramowania, a główny element UIView ma ograniczenia o wartości 2 z każdej strony.
Połączę widok tła z moim ViewController, a następnie włączam i wyłączam obramowanie, zmieniając kolor tła.
źródło
Szybki 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() } }
źródło