2011-01-30 45 views
18

Trong ứng dụng iPad của tôi, tôi muốn một lần xem thứ hai xuất hiện trong chính khi người dùng nhấp vào một nút. Giao diện mới sẽ nhỏ hơn lần đầu tiên và làm tối nền khi nó được hiển thị. Tôi muốn hai góc trên cùng của giao diện mới xuất hiện được làm tròn, nhưng sử dụng cornerRadius đặt tất cả chúng được làm tròn. Làm thế nào tôi có thể làm cho hai góc tròn?Chỉ cần hai góc tròn?

Trả lời

17

Bạn phải làm điều này trong drawRect :. Tôi thực sự sửa đổi addRoundedRectToPath cổ điển: để nó mất một bitmap và viên đạn các góc quý vị yêu cầu:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, UIImageRoundedCorner cornerMask) 
{ 
    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius); 
    CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius); 
    if (cornerMask & UIImageRoundedCornerTopLeft) { 
     CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, 
         radius, M_PI, M_PI/2, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height); 
     CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y + rect.size.height); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, 
          rect.origin.y + rect.size.height); 

    if (cornerMask & UIImageRoundedCornerTopRight) { 
     CGContextAddArc(context, rect.origin.x + rect.size.width - radius, 
         rect.origin.y + rect.size.height - radius, radius, M_PI/2, 0.0f, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - radius); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius); 

    if (cornerMask & UIImageRoundedCornerBottomRight) { 
     CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius, 
         radius, 0.0f, -M_PI/2, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y); 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, rect.origin.y); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y); 

    if (cornerMask & UIImageRoundedCornerBottomLeft) { 
     CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius, 
         -M_PI/2, M_PI, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y); 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + radius); 
    } 

    CGContextClosePath(context); 
} 

này có một bitmask (tôi gọi nó UIImageRoundedCorner bởi vì tôi đã làm điều này cho hình ảnh, nhưng bạn có thể gọi nó là bất cứ điều gì) và sau đó xây dựng một đường dẫn dựa trên các góc bạn muốn làm tròn. Sau đó, bạn áp dụng con đường đó để xem trong drawRect:

CGContextBeginPath(context); 
addRoundedRectToPath(context, rect, radius, yourMask); 
CGContextClosePath(context); 
CGContextClip(context); 

Như tôi đã nói, tôi đã làm điều này cho UIImages, do đó, mã của tôi là không chính xác thiết lập để sử dụng trong drawRect :, nhưng nó nên được khá dễ dàng để thích ứng với nó. Về cơ bản, bạn chỉ xây dựng một con đường và sau đó cắt bớt ngữ cảnh cho nó.

Edit: Để giải thích phần bitmask, nó chỉ là một enum:

typedef enum { 
    UIImageRoundedCornerTopLeft = 1, 
    UIImageRoundedCornerTopRight = 1 << 1, 
    UIImageRoundedCornerBottomRight = 1 << 2, 
    UIImageRoundedCornerBottomLeft = 1 << 3 
} UIImageRoundedCorner; 

Bằng cách này bạn có thể HOẶC thứ lại với nhau để tạo thành một bitmask xác định góc, vì mỗi thành viên của enum đại diện cho một sức mạnh khác nhau của hai trong bitmask.

Hầu Sửa Sau đó: Tôi đã phát hiện ra một cách dễ dàng hơn để làm điều này bằng UIBezierPath 's bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:. Chỉ cần sử dụng đối tượng đường dẫn bezier CGPath trong ngữ cảnh của bạn.

+0

Great câu trả lời! Chỉ cần một sự trợ giúp để thực hiện nó. Trước hết, làm thế nào tôi có thể làm cho bitmask của riêng tôi? – Jumhyn

+0

Chỉnh sửa câu trả lời để giải thích enum. – kevboh

+0

Câu trả lời của tôi được xây dựng để lấy bất kỳ góc nào bạn muốn làm tròn. Nếu bạn chỉ cần hai góc trên cùng và không quan tâm đến những người khác, bạn có thể chỉnh sửa bitmask vô nghĩa và chỉ sử dụng hai phần tương ứng với các góc bạn cần làm tròn. – kevboh

56
// Create the path (with only the top-left corner rounded) 
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
          byRoundingCorners:UIRectCornerTopLeft| UIRectCornerTopRight 
          cornerRadii:CGSizeMake(10.0, 10.0)]; 
// Create the shape layer and set its path 
CAShapeLayer *maskLayer = [CAShapeLayer layer]; 
maskLayer.frame = imageView.bounds; 
maskLayer.path = maskPath.CGPath; 
// Set the newly created shape layer as the mask for the image view's layer 
imageView.layer.mask = maskLayer; 

Đây là cách khác để sử dụng góc được làm tròn trên cùng. Round two corners in UIView

+2

Thats hoạt động tốt .. cảm ơn rất nhiều –

+0

Điều đó hoạt động, NHƯNG gây ra hiển thị offscreen trong toàn bộ khu vực 'imageView', dẫn đến hoạt ảnh lộn xộn – Philip007

+0

Câu trả lời hay nhất mà tôi đã tìm thấy về chủ đề này! – PaperThick

8

Công việc tuyệt vời được thực hiện bởi Tomek Kuźma. Đây là lớp TKRoundedView mới cho yêu cầu của bạn.
Yêu cầu của bạn chỉ có thể được thực hiện bởi tham số này.

TKRoundedView *view = [[TKRoundedView alloc] initWithFrame:frame]; 
view.roundedCorners = TKRoundedCornerTopLeft | TKRoundedCornerTopRight; 

Nhưng nó cũng cung cấp các tính năng bổ sung sau đây.

TKRoundedView *view = [[TKRoundedView alloc] initWithFrame:frame]; 
view.roundedCorners = TKRoundedCornerTopLeft 
view.borderColor = [UIColor greenColor]; 
view.fillColor = [UIColor whiteColor]; 
view.drawnBordersSides = TKDrawnBorderSidesLeft | TKDrawnBorderSidesTop; 
view.borderWidth = 5.0f; 
view.cornerRadius = 15.0f; 

Hãy kiểm tra các liên kết sau để ví dụ dự án
https://github.com/mapedd/TKRoundedView

+0

^rất tốt! Hoạt động tốt với bố cục tự động. –