[ios] UIView 외부에 테두리 추가 (내부 대신)

다음과 같은보기에서 코드를 사용하여보기의 테두리를 추가하면

self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;

테두리는 다음과 같이 뷰 내부에 추가됩니다.
여기에 이미지 설명 입력

오른쪽보기는 원래보기입니다. 보시다시피 테두리가있는보기의 검은 색 영역은 원래보기보다 작습니다. 하지만 내가 얻고 싶은 것은 다음과 같이 원래보기 외부의 테두리 여기에 이미지 설명 입력입니다. 검은 색 영역이 원래 영역과 동일합니다. 어떻게 구현할 수 있습니까?



답변

안타깝게도 테두리를 바깥쪽에 맞추기 위해 설정할 수있는 속성은 간단하지 않습니다. 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그에 따라 레이어의 프레임을 조정하는 것 입니다. 이것은 더 나은 두 번째보기 a를 사용하는 것보다이 같이 큰 비트입니다 CALayer(A)보다 가볍다 UIView그리고 당신의 프레임 수정 할 수없는 myView경우 예를 들어 좋은이며, myViewA는UIImageView

NB : 저에게 결과는 시뮬레이터에서 완벽하지 않았습니다 (레이어가 정확히 올바른 위치에 있지 않아서 가끔 레이어가 한쪽면이 더 두꺼 웠습니다). 실제 장치에서 정확히 요구하는 내용이었습니다.

편집하다

사실 NB 에서 제가 이야기하는 문제 는 시뮬레이터의 화면을 줄 였기 때문에 정상적인 크기에서는 전혀 문제가 없습니다

도움이되기를 바랍니다.


답변

위의 수락 된 베스트 답변으로 나는 그러한 경험을했습니다. 좋지 않은 결과와보기 흉한 가장자리를 .

베 지어 경로가없는 테두리

따라서 보기 흉한 가장자리없이 UIBezierPath를 테두리 윤곽선으로 사용하는 UIView Swift 확장 기능을 공유 하겠습니다 ( @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()
    }

}


답변

직접적인 방법은 없습니다. 몇 가지 해결 방법을 고려할 수 있습니다.

  1. 프레임을 변경하고 늘리고 테두리 색상을 추가하십시오.
  2. 현재 뷰 뒤에 더 큰 크기의 뷰를 추가하여 테두리로 표시합니다. 사용자 정의 뷰 클래스로 작업 할 수 있습니다.
  3. 명확한 테두리 (클리어 컷 테두리)가 필요하지 않은 경우 목적을 위해 그림자에 의존 할 수 있습니다.

    [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