UIView에서 두 모서리 라운드


82

얼마 전에 뷰의 두 모서리 만 둥글게 하는 것에 대한 질문을 올렸고 훌륭한 응답을 받았지만 구현하는 데 문제가 있습니다. 내 drawRect : 메서드는 다음과 같습니다.

- (void)drawRect:(CGRect)rect {
    //[super drawRect:rect]; <------Should I uncomment this?
    int radius = 5;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGContextClosePath(context);
    CGContextClip(context);
}

메서드가 호출되고 있지만 뷰의 결과에 영향을주지 않는 것 같습니다. 이유는 무엇입니까?

답변:


103

CACornerMask는 , 뷰 레이어에서 오른쪽 아래를, 좌상 정의 topright, bottomleft하는 데 도움이 아이폰 OS (11)에 소개했다. 아래는 사용 예입니다.

여기에서는 상단 모서리 두 개만 둥글게 만들려고합니다.

myView.clipsToBounds = true
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]

FYI 참조 :


이것은 지금 이것을하는 관용적 인 방법처럼 보입니다. 잘 잡아!
Jumhyn

2
뷰의 너비 / 높이는 여전히 모서리 반경의 두 배 이상이어야합니다. 그렇지 않으면 이상한 아티팩트가 나타납니다. 예를 들어 하단 모서리 만 둥글게, 반경 20, 높이 30 만하면 셀이 눈에 띄게 좁아집니다 (1 픽셀 또는 2 픽셀).
Graham Perks

보기가 (- 내 경우로 인해 확장 UITextView에 수의 프레임을 변경하는 경우이 올바른 방법이라고 주 stackoverflow.com/questions/50926215/... ). UIBezierPath를 설정하면 프레임이 변경 될 때 자동으로 업데이트되지 않습니다.
thomers

이 아이폰 OS 11 이상에서만 사용할 수주의if #available(iOS 11.0, *) { }
트라이 Ngo의 호치민

2
좋은 대답입니다. 설정 밝혀 clipsToBounds으로는 true필요하지 않습니다. 당신은 모서리 마스크 때 레이어에 그림자를 추가 할 수 clipsToBounds있습니다 false. 나를 위해 편리하게 왔습니다.
Au Ris

72


내가 아는 한, 하위 뷰도 CALayer마스킹 해야하는 경우 마스킹을 사용할 수 있습니다 . 이를 수행하는 두 가지 방법이 있습니다. 첫 번째는 좀 더 우아하고 두 번째는 해결 방법입니다. :-)하지만 빠릅니다. 둘 다 CALayer마스킹을 기반으로 합니다. 작년에 몇 개의 프로젝트에서 두 가지 방법을 모두 사용했으며 유용한 것을 찾을 수 있기를 바랍니다.

해결책 1

우선, UIImage필요한 둥근 모서리가 있는 즉석에서 이미지 마스크 ( ) 를 생성하기 위해이 함수를 만들었습니다 . 이 함수에는 기본적으로 5 개의 매개 변수가 필요합니다 : 이미지의 경계와 4 개의 코너 반경 (왼쪽 상단, 오른쪽 상단, 왼쪽 하단 및 오른쪽 하단).


static inline UIImage* MTDContextCreateRoundedMask( CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br ) {  

    CGContextRef context;
    CGColorSpaceRef colorSpace;

    colorSpace = CGColorSpaceCreateDeviceRGB();

    // create a bitmap graphics context the size of the image
    context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );

    // free the rgb colorspace
    CGColorSpaceRelease(colorSpace);    

    if ( context == NULL ) {
        return NULL;
    }

    // cerate mask

    CGFloat minx = CGRectGetMinX( rect ), midx = CGRectGetMidX( rect ), maxx = CGRectGetMaxX( rect );
    CGFloat miny = CGRectGetMinY( rect ), midy = CGRectGetMidY( rect ), maxy = CGRectGetMaxY( rect );

    CGContextBeginPath( context );
    CGContextSetGrayFillColor( context, 1.0, 0.0 );
    CGContextAddRect( context, rect );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    CGContextSetGrayFillColor( context, 1.0, 1.0 );
    CGContextBeginPath( context );
    CGContextMoveToPoint( context, minx, midy );
    CGContextAddArcToPoint( context, minx, miny, midx, miny, radius_bl );
    CGContextAddArcToPoint( context, maxx, miny, maxx, midy, radius_br );
    CGContextAddArcToPoint( context, maxx, maxy, midx, maxy, radius_tr );
    CGContextAddArcToPoint( context, minx, maxy, minx, midy, radius_tl );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    // Create CGImageRef of the main view bitmap content, and then
    // release that bitmap context
    CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
    CGContextRelease( context );

    // convert the finished resized image to a UIImage 
    UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
    // image is retained by the property setting above, so we can 
    // release the original
    CGImageRelease(bitmapContext);

    // return the image
    return theImage;
}  

이제 몇 줄의 코드 만 있으면됩니다. viewDidLoad더 빠르기 때문에 viewController 메서드 에 항목을 넣었 지만 예제 UIViewlayoutSubviews메서드를 사용하여 사용자 정의에서도 사용할 수 있습니다 .



- (void)viewDidLoad {

    // Create the mask image you need calling the previous function
    UIImage *mask = MTDContextCreateRoundedMask( self.view.bounds, 50.0, 50.0, 0.0, 0.0 );
    // Create a new layer that will work as a mask
    CALayer *layerMask = [CALayer layer];
    layerMask.frame = self.view.bounds;       
    // Put the mask image as content of the layer
    layerMask.contents = (id)mask.CGImage;       
    // set the mask layer as mask of the view layer
    self.view.layer.mask = layerMask;              

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

해결 방법 2

이 솔루션은 좀 더 "더럽습니다". 기본적으로 필요한 둥근 모서리 (모든 모서리)로 마스크 레이어를 만들 수 있습니다. 그런 다음 모서리 반경 값만큼 마스크 레이어의 높이를 늘려야합니다. 이런 식으로 하단의 둥근 모서리가 숨겨지고 상단의 둥근 모서리 만 볼 수 있습니다. viewDidLoad더 빠르기 때문에 메서드에 코드를 넣었 지만 예제 UIViewlayoutSubviews메서드를 사용하여 사용자 정의에서도 사용할 수 있습니다 .

  

- (void)viewDidLoad {

    // set the radius
    CGFloat radius = 50.0;
    // set the mask frame, and increase the height by the 
    // corner radius to hide bottom corners
    CGRect maskFrame = self.view.bounds;
    maskFrame.size.height += radius;
    // create the mask layer
    CALayer *maskLayer = [CALayer layer];
    maskLayer.cornerRadius = radius;
    maskLayer.backgroundColor = [UIColor blackColor].CGColor;
    maskLayer.frame = maskFrame;

    // set the mask
    self.view.layer.mask = maskLayer;

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

도움이 되었기를 바랍니다. 챠오!


마침내 작동했습니다! 정말 고마워! 다른 것보다 하나의 장점은 무엇입니까?
Jumhyn

어쨌든 CAShapeLayer 솔루션조차도 완벽합니다. UIBezierPath (3.2 이상 필요)를 사용하거나 CGPath 메소드 (CGPathMoveToPoint, CGPathAddQuadCurveToPoint 등)를 사용하여 CGPath를 그릴 수 있습니다.
lomanf

1
세로에서 가로로 회전 한 후 마스크 크기를 자동으로 조정하려면 어떻게해야합니까?
chourobin

YES = layer.masksToBounds를 추가하는 것을 잊지 마세요
드미트리 Salnikov

오른쪽 상단 및 하단 모서리 만 둥글게 만들려면 어떻게해야합니까?
PLOW

69

몇 가지 답변 및 의견을 통해 빗질, 내가 사용하는 것을 발견 UIBezierPath bezierPathWithRoundedRect하고 CAShapeLayer가장 단순하고 정직 방법. 매우 복잡한 경우에는 적합하지 않을 수 있지만 가끔 모서리를 둥글게하는 경우에는 빠르고 원활하게 작동합니다.

마스크에 적절한 모서리를 설정하는 간단한 도우미를 만들었습니다.

-(void) setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
    UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(10.0, 10.0)];

    CAShapeLayer* shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];

    view.layer.mask = shape;
}

이를 사용하려면 적절한 UIRectCorner 열거 형으로 호출하기 만하면됩니다. 예 :

[self setMaskTo:self.photoView byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomLeft];

저에게는 그룹화 된 UITableViewCell에서 사진의 모서리를 둥글게하는 데 사용합니다. 적절한 값을 변경해야하는 경우 10.0 반경이 잘 작동합니다.

편집 : 이전에 이것과 매우 유사하게 답변 한 것을 주목하십시오 ( 링크 ). 필요한 경우이 답변을 추가 편의 기능으로 계속 사용할 수 있습니다.


편집 : Swift 3의 UIView 확장과 동일한 코드

extension UIView {
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

사용하려면 다음 maskByRoundingCorner중 하나를 호출 하면됩니다 UIView.

view.maskByRoundingCorners([.topLeft, .bottomLeft])

여전히 테두리를 추가하는 동안 가능합니까?
Unome

2
나는 단지 하나의 모서리가 둥근있어 때문에 DispatchQueue.main.async {}로 함수 호출을 넣어했다 ...
막심 Kniazev

1
@MaksimKniazev 예, 메인 (UI) 스레드에서 호출해야합니다. 이 규칙은 UI를 건 드리는 모든 작업에 적용되며, 기본 스레드에서 호출해야합니다. 그렇지 않으면 이상한 일이 발생할 수 있습니다.
PL

1
한쪽 모서리 만 둥글게 보입니다. @MaksimKniazev 솔루션을 시도했지만 작동하지 않았습니다.
Gustavo_fringe

@Gustavo_fringe와 동일한 문제가 있는데, 오른쪽 상단 모서리가 xib 뷰 내부의 경계로 잘 리거나 마스킹되지 않고 아직 수정하는 방법을 모르겠습니다.
CyberMew

57

@lomanf의 답변에 대한 의견에이 모든 것을 넣을 수는 없습니다. 그래서 나는 그것을 대답으로 추가하고 있습니다.

@lomanf가 말했듯이 하위 레이어가 경로 경계를 벗어나는 것을 방지하려면 레이어 마스크를 추가해야합니다. 하지만 지금은 훨씬 더 쉽습니다. iOS 3.2 이상을 대상으로하는 한 석영으로 이미지를 만들고 마스크로 설정할 필요가 없습니다. 을 사용하여 CAShapeLayer를 만들고 UIBezierPath마스크로 사용할 수 있습니다 .

또한 레이어 마스크를 사용할 때 마스크를 추가 할 때 마스크 할 레이어가 레이어 계층의 일부가 아닌지 확인하십시오. 그렇지 않으면 동작이 정의되지 않습니다. 뷰가 이미 계층 구조에있는 경우 수퍼 뷰에서 제거하고 마스킹 한 다음 원래 위치로 되돌려 야합니다.

CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *roundedPath = 
  [UIBezierPath bezierPathWithRoundedRect:maskLayer.bounds
                        byRoundingCorners:UIRectCornerTopLeft |
                                          UIRectCornerBottomRight
                              cornerRadii:CGSizeMake(16.f, 16.f)];    
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];

//Don't add masks to layers already in the hierarchy!
UIView *superview = [self.view superview];
[self.view removeFromSuperview];
self.view.layer.mask = maskLayer;
[superview addSubview:self.view];

Core Animation 렌더링이 작동하는 방식으로 인해 마스킹은 상대적으로 느린 작업입니다. 각 마스크에는 추가 렌더링 패스가 필요합니다. 따라서 마스크를 아껴 사용하십시오.

이 접근 방식의 가장 좋은 부분 중 하나는 더 이상 사용자 지정 UIView을 만들고을 재정의 할 필요가 없다는 것 drawRect:입니다. 이렇게하면 코드가 더 간단하고 더 빨라질 것입니다.


유망 해 보이지만보기가 나타나지 않습니다. 이유는 무엇입니까?
Jumhyn

10
maskLayer.bounds를 사용하여 UIBezierPath의 크기를 조정하고 있지만 경계 값은 CGRectZero입니다. maskLayer.frame = self.view.bounds와 같은 두 번째 코드 줄 (CAShapeLayer 초기화 직후)을 추가해야합니다.
lomanf

1
네 말이 맞아. 모양 레이어가 이미 존재하는 다른 예제에서 해당 코드를 추출했습니다. 미안합니다.
Nathan Eror

완벽하게 작동합니다! 위에서 언급했듯이 maskLayer.frame = self.view.bounds를 추가하면 make가 작동합니다. 그렇지 않으면보기가 표시되지 않습니다.
Daniel Ribeiro

+1 이것은 아주 잘 작동합니다. 사실 저는 lomanf의 # 2 솔루션보다이 방법을 선호한다고 생각합니다. 이 방법을 사용하면 반대쪽 모서리 (예 : 오른쪽 위 + 왼쪽 아래)에 호를 쉽게 추가 할 수 있으며 lomanf의 첫 번째 솔루션보다 확실히 짧습니다. 위대한 코드 Nathan!
FreeAsInBeer 2013 년

30

나는 Nathan의 예를 들어 UIViewDRY 원칙을 고수 할 수 있도록 카테고리를 만들었습니다 . 더 이상 고민하지 않고 :

UIView + Roundify.h

#import <UIKit/UIKit.h>

@interface UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;

@end

UIView + Roundify.m

#import "UIView+Roundify.h"

@implementation UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CALayer *tMaskLayer = [self maskForRoundedCorners:corners withRadii:radii];
    self.layer.mask = tMaskLayer;
}

-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = self.bounds;

    UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:
        maskLayer.bounds byRoundingCorners:corners cornerRadii:radii];
    maskLayer.fillColor = [[UIColor whiteColor] CGColor];
    maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
    maskLayer.path = [roundedPath CGPath];

    return maskLayer;
}

@end

전화하려면 :

[myView addRoundedCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                withRadii:CGSizeMake(20.0f, 20.0f)];

2
.m 파일에서 <QuartzCore / QuatzCore.h>를 가져 와서 QuartzCore.framework를 프로젝트에 추가하는 것을
잊지 마십시오

+1 멋진 것, 한 가지 질문입니다. 뷰를 수퍼 뷰로 제거 / 읽는 목적은 무엇입니까?
eladleb

@eladleb : 여기에있는 기본 코드는 Nathan이 만든 것입니다. 간단히 약간 최적화했습니다. 내가 한 연구에서 레이어 마스크를 적용하기 전에 뷰를 제거해야하는 유효한 이유를 찾을 수 없습니다. 따라서 해당 코드를 생략하는 것이 안전하다고 생각합니다.
FreeAsInBeer 2013-08-13

@FreeAsInBeer는 - 그때 내가 그것을 제거하기 위해 투표 것, 동의,이 사실은 ..보기 z 순서를 변경하고 더 많은 문제를 만들 수 있습니다
eladleb

TableView에 둥근 모서리를 추가 할 때 발생한 문제를 해결했습니다. 머리글, 둥근 홑 모서리를 추가하고 둥근 하단 모서리가있는 바닥 글을 추가했습니다. 감사.
nightfixed

24

PL의 답변을 조금 확장하기 위해 UIButton정확하게 같은 특정 객체를 반올림하지 않도록 방법을 다시 작성했습니다.

- (void)setMaskTo:(id)sender byRoundingCorners:(UIRectCorner)corners withCornerRadii:(CGSize)radii
{
    // UIButton requires this
    [sender layer].cornerRadius = 0.0;

    UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:[sender bounds]
                                                byRoundingCorners:corners
                                                cornerRadii:radii];

    CAShapeLayer *newCornerLayer = [CAShapeLayer layer];
    newCornerLayer.frame = [sender bounds];
    newCornerLayer.path = shapePath.CGPath;
    [sender layer].mask = newCornerLayer;
}

그리고 그것을 부르십시오

[self setMaskTo:self.continueButton byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight withCornerRadii:CGSizeMake(3.0, 3.0)];

12

Swift에서하고 싶다면 UIView. 이렇게하면 모든 하위 클래스에서 다음 메서드를 사용할 수 있습니다.

import QuartzCore

extension UIView {
    func roundCorner(corners: UIRectCorner, radius: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.CGPath
        layer.mask = maskLayer
    }
}    

사용 예 :

self.anImageView.roundCorner(.topRight, radius: 10)

3

허용되는 답변을 확장하여 이전 버전과의 호환성을 추가하겠습니다. iOS 11 이전에는 view.layer.maskedCorners를 사용할 수 없습니다. 그래서 우리는 이렇게 할 수 있습니다

if #available(iOS 11.0, *) {
    myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
} else {
    myView.maskByRoundingCorners([.topLeft, .topRight])
}

extension UIView{
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

코드 재사용을 향상시키기 위해 maskByRoundingCorners를 UIView 확장으로 작성했습니다.

@SachinVsSachin 및 @PL에 대한 크레딧 :) 더 나은 코드를 만들기 위해 코드를 결합했습니다.


2
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(5, 5, self.bounds.size.width-10, self.bounds.size.height-10)
                                               byRoundingCorners:UIRectCornerAllCorners
                                                     cornerRadii:CGSizeMake(12.0, 12.0)];

필요에 따라 "AllCorners"를 변경 하십시오.


그래서 당신은 UIView에서 이것을해야합니까 아니면 UIViewController에서 이것을 할 수 있습니까? UIBezierPath를 만든 후에는 무엇을합니까? 감사.
StoneBreaker 2012-06-07

2

제공된 모든 솔루션이 목표를 달성합니다. 그러나 UIConstraints때때로 이것을 날려 버릴 수 있습니다.

예를 들어, 하단 모서리는 둥글어야합니다. 반올림해야하는 UIView에 높이 또는 하단 간격 제약 조건이 설정된 경우 모서리를 반올림하는 코드 조각을 viewDidLayoutSubviews메서드 로 이동해야 합니다.

강조 :

UIBezierPath *maskPath = [UIBezierPath
    bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:
    (UIRectCornerTopRight | UIRectCornerBottomRight) cornerRadii:CGSizeMake(16.0, 16.0)];

위의 코드 스 니펫은이 코드가 viewDidLoad. 때문에 roundedView.bounds제약 후 변화에려고하고를 업데이트합니다 UIView.



1

코드로 시작하면 아래 스 니펫과 같은 것을 사용할 수 있습니다.

이것이 당신이 추구하는 결과인지 확실하지 않습니다. 또한 시스템이 drawRect :를 호출 할 때 rect의 일부만 다시 그려달라고 요청하면 매우 이상하게 동작 할 것입니다. 위에서 언급 한 Nevan의 접근 방식 이 더 나은 방법 일 수 있습니다.

 // make sure the view's background is set to [UIColor clearColor]
- (void)drawRect:(CGRect)rect
{
    CGFloat radius = 10.0;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, rect.size.width/2, rect.size.height/2);
    CGContextRotateCTM(context, M_PI); // rotate so image appears right way up
    CGContextTranslateCTM(context, -rect.size.width/2, -rect.size.height/2);

    CGContextBeginPath(context);

    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
    CGContextClip(context); 

    // now do your drawing, e.g. draw an image
    CGImageRef anImage = [[UIImage imageNamed:@"image.jpg"] CGImage];
    CGContextDrawImage(context, rect, anImage);    
}

모서리가 둥근 뷰를 만들었지 만 하위 뷰를 잘라낼 수 없습니다. 내 뷰의 가장자리에 정사각형 모서리가있는 뷰를 배치해도 수퍼 뷰의 둥근 모서리가 여전히 덮입니다. 왜 이런 일이 일어나는지 아십니까?
Jumhyn

클리핑 -drawRect:은 그리는 뷰에만 영향을 미치기 때문입니다. 도면이 완료된 후 하위 뷰가 독립적으로 그려집니다.
Jonathan Grynspan

1

약간 해키하지만 상대적으로 간단한 (서브 클래 싱, 마스킹 등이없는) 방법은 두 개의 UIView를 갖는 것입니다. 둘 다 clipToBounds = YES. 하위 뷰에 둥근 모서리를 설정 한 다음 똑바로 원하는 모서리가 잘 리도록 상위 뷰 내에 배치합니다.

UIView* parent = [[UIView alloc] initWithFrame:CGRectMake(10,10,100,100)];
parent.clipsToBounds = YES;

UIView* child = [[UIView alloc] new];
child.clipsToBounds = YES;
child.layer.cornerRadius = 3.0f;
child.backgroundColor = [UIColor redColor];
child.frame = CGRectOffset(parent.bounds, +4, -4);


[parent addSubView:child];

대각선으로 마주 보는 두 모서리를 둥글게하고 싶은 경우는 지원하지 않습니다.


1

추가 코드가 필요한 경우 Bezier 경로가 답입니다. https://stackoverflow.com/a/13163693/936957

UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:_backgroundImageView.bounds 
                                 byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                                       cornerRadii:CGSizeMake(3.0, 3.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
_backgroundImageView.layer.mask = maskLayer;
[maskLayer release];

1

UIBezierPath 솔루션.

- (void) drawRect:(CGRect)rect {

    [super drawRect:rect];

    //Create shape which we will draw. 
    CGRect rectangle = CGRectMake(2, 
                                  2, 
                                  rect.size.width - 4,
                                  rect.size.height - 4);

    //Create BezierPath with round corners
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rectangle 
                                                   byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight 
                                                         cornerRadii:CGSizeMake(10.0, 10.0)];

    //Set path width
    [maskPath setLineWidth:2];

    //Set color
    [[UIColor redColor] setStroke];

    //Draw BezierPath to see it
    [maskPath stroke];
}

0

다음과 같이 올바르게 설정된 경우에만 작동 할 수 있습니다.

  1. clipsToBounds는 YES로 설정되어야합니다.
  2. 불투명은 NO 여야합니다.
  3. backgroundColor는 "clearColor"여야합니다 (확실하지 않음).
  4. drawRect는 그렇지 않은 경우 자주 호출되지 않으므로 contentMode는 "UIContentModeRedraw"여야합니다.
  5. [super drawRect : rect]는 CGContextClip 후에 호출되어야합니다.
  6. 보기에 임의의 하위보기가 포함되어 있지 않을 수 있습니다 (확실하지 않음)
  7. drawrect를 트리거하려면 "needsDisplay :"를 한 번 이상 설정해야합니다.

0

UITableView의 상단 두 모서리를 둥글게 만들려고한다는 것을 알고 있지만 어떤 이유로 가장 좋은 해결책은 다음을 사용하는 것입니다.

self.tableView.layer.cornerRadius = 10;

프로그래밍 방식으로 네 모서리를 모두 둥글게해야하지만 어떤 이유로 상단 2 개만 둥글게합니다. ** 위에 작성한 코드의 효과를 확인하려면 아래 스크린 샷을 참조하십시오.

이게 도움이 되길 바란다!

여기에 이미지 설명 입력


1
그것은 모든 모서리 라운딩되어 있지 않은 경우 UITableView제작되어 다음이 있어야 코드를 다른 곳에서 UITableView바닥에하지 않은 모서리를 둥글게, 또는 어쩌면 UIViewUILabel그가의 하단 부분을 포함됩니다 UITableView.
Josh Valdivieso

-1

경계에 맞게 클립해야 할 것입니다. 라인 추가

self.clipsToBounds = YES

코드의 어딘가에 해당 속성을 설정합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.