2009-06-15 72 views

Trả lời

66

Bạn có thể sử dụng CoreGraphics để tạo ra một con đường cho một hình chữ nhật tròn với đoạn mã này:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight) 
{ 
    float fw, fh; 
    if (ovalWidth == 0 || ovalHeight == 0) { 
     CGContextAddRect(context, rect); 
     return; 
    } 
    CGContextSaveGState(context); 
    CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect)); 
    CGContextScaleCTM (context, ovalWidth, ovalHeight); 
    fw = CGRectGetWidth (rect)/ovalWidth; 
    fh = CGRectGetHeight (rect)/ovalHeight; 
    CGContextMoveToPoint(context, fw, fh/2); 
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); 
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); 
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); 
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); 
    CGContextClosePath(context); 
    CGContextRestoreGState(context); 
} 

Và sau đó gọi CGContextClip (context); để clip nó vào đường dẫn hình chữ nhật. Bây giờ bất kỳ bản vẽ nào được thực hiện, bao gồm vẽ một hình ảnh, sẽ được cắt bớt thành hình chữ nhật tròn.

Như một ví dụ, giả sử "hình ảnh" là một UIImage, và đây là một trong drawRect: phương pháp:

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(context); 
addRoundedRectToPath(context, self.frame, 10, 10); 
CGContextClip(context); 
[image drawInRect:self.frame]; 
CGContextRestoreGState(context); 
+8

Answer vì toán học là mát mẻ – slf

+0

Điều đó có vẻ rất hữu ích, nhưng tôi không quen thuộc với thư viện CG. Nếu tôi có UIImageView/UIImage, tôi sẽ đi đâu từ đó? – erotsppa

+0

Bạn sẽ muốn triển khai phương thức drawRect trên khung nhìn với mã tôi đã thêm ở trên. – NilObject

34

Dưới đây là một phương pháp dễ dàng hơn đó là có sẵn trong iPhone 3.0 trở lên. Mỗi đối tượng dựa trên dạng xem đều có một lớp liên quan. Mỗi lớp có thể có một bộ bán kính góc, điều này sẽ cung cấp cho bạn chỉ là những gì bạn muốn:

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]]; 
// Get the Layer of any view 
CALayer * layer = [roundedView layer]; 
[layer setMasksToBounds:YES]; 
[layer setCornerRadius:10.0]; 

// You can even add a border 
[layer setBorderWidth:4.0]; 
[layer setBorderColor:[[UIColor blueColor] CGColor]]; 

Để sử dụng các phương pháp bạn có thể cần phải thêm:

#import <QuartzCore/QuartzCore.h> 
+1

Phương pháp CoreGraphics ở trên được đăng bởi NilObject nhanh hơn khi bạn đang xử lý các mục động. Dường như bán kính góc được xây dựng không hiệu quả. – MagicSeth

+2

Cảm ơn! Nếu bất cứ ai gặp rắc rối với điều này, hãy chắc chắn #import trong tệp triển khai của bạn, nếu không thì không có phương thức nào trong số đó sẽ bay. –

+1

Ở đây bạn đang phân bổ một đối tượng UIImageView. Đây không phải là một tùy chọn khi bạn xử lý hình ảnh trong UITableViews. – samvermette

2

Xem this Post - Câu trả lời rất đơn giản

How to set round corners in UI images in iphone

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]]; 
// Get the Layer of any view 
CALayer * l = [roundedView layer]; 
[l setMasksToBounds:YES]; 
[l setCornerRadius:10.0]; 
0

Cả hai phương pháp làm việc nhưng sự khác biệt SHO ws up tùy thuộc vào nơi bạn sử dụng nó.

Ví dụ: Nếu bạn có chế độ xem bảng với các ô hiển thị hình ảnh cùng với các nhãn khác, v.v. và bạn sử dụng lớp để đặt gócRadius, cuộn sẽ có một lần truy cập lớn. Nó bị giật.

Tôi gặp phải sự cố này khi tôi đang sử dụng Lớp cho hình ảnh trong ô xem bảng và đang cố gắng tìm ra nguyên nhân của sự giật giật đó chỉ để thấy rằng CALayer là thủ phạm.

Sử dụng giải pháp đầu tiên để thực hiện công cụ trong drawRect được giải thích bởi NilObject. Điều đó hoạt động như một nét duyên dáng với cuộn mượt mà như lụa.

Mặt khác, nếu bạn muốn sử dụng điều này trong chế độ xem tĩnh như chế độ xem cửa sổ bật lên, v.v., lớp là cách dễ nhất để thực hiện.

Như tôi đã nói, cả hai phương pháp hoạt động tốt chỉ cần bạn quyết định dựa trên nơi bạn muốn sử dụng.

0

Tôi sử dụng phương pháp này.

+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size; 
    { 
     UIImage *img = nil; 


     CGRect rect = CGRectMake(0, 0, size.width, size.height); 
     UIGraphicsBeginImageContext(rect.size); 
     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextSetFillColorWithColor(context, 
            color.CGColor); 
     CGContextFillRect(context, rect); 
     img = UIGraphicsGetImageFromCurrentImageContext(); 

     UIGraphicsEndImageContext(); 


     return img; 
    } 
+2

Theo quy tắc quản lý bộ nhớ, đối tượng hình ảnh được trả về bởi 'UIGraphicsGetImageFromCurrentImageContext' không cần phải được giữ lại, vì vậy bạn sẽ bị rò rỉ bộ nhớ ở đó. Đó là người gọi của 'imageWithColor' cần giữ lại nó. Có lẽ bạn đã thêm phần giữ lại vì 'NSAutoreelasePool' (cũng có vẻ đáng ngờ)? –

15

Tôi nhận ra đây là tin cũ nhưng chỉ để đun sôi nó xuống một chút:

hai câu hỏi có thể ở đây: (1) làm thế nào để áp dụng các góc tròn đến một UIView (ví dụ như một UIImageView), sẽ được hiển thị trên màn hình và (2) làm cách nào để che một hình ảnh vuông (nghĩa là UIImage) để tạo ra một hình ảnh mới với các góc tròn.

Đối với (1), khóa học dễ nhất là sử dụng CoreAnimation và đặt view.layer.tài sản cornerRadius

// Because we're using CoreAnimation, we must include QuartzCore.h 
// and link QuartzCore.framework in a build phases 
#import <QuartzCore/QuartzCore.h> 

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"]; 
// put it in a UIImageView 
UIView * view = [UIImageView alloc] initWithImage:fooImage]; 
// round its corners. This mask now applies to the view's layer's *background* 
view.layer.cornerRadius = 10.f 
// enable masksToBounds, so the mask applies to its foreground, the image 
view.layer.masksToBounds = YES; 

Đối với (2), cách tốt nhất là sử dụng các thao tác đồ họa UIKit:

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"]; 
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height); 
// set the implicit graphics context ("canvas") to a bitmap context for images 
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); 
// create a bezier path defining rounded corners 
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f]; 
// use this path for clipping in the implicit context 
[path addClip]; 
// draw the image into the implicit context 
[fooImage drawInRect:imageRect]; 
// save the clipped image from the implicit context into an image 
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext(); 
// cleanup 
UIGraphicsEndImageContext(); 

Có gì khó khăn về vấn đề (2) là bạn có thể nghĩ rằng bạn có thể làm toàn bộ hoạt động bằng cách sử dụng thuộc tính view.layer.mask trong CoreAnimation. Nhưng bạn không thể vì phương thức CALayer renderInContext: mà bạn sử dụng để tạo UIImage từ lớp mặt nạ, dường như bỏ qua mặt nạ. Tệ hơn nữa, tài liệu cho renderInContext: không đề cập đến điều này và chỉ ám chỉ hành vi của OSX 10.5.

Một số ngữ cảnh nữa: cách tiếp cận trên tới (2) đang sử dụng trình bao bọc của UIKit xung quanh chức năng CoreGraphics cơ bản hơn. Bạn có thể làm điều tương tự bằng cách sử dụng các cuộc gọi CoreGraphics trực tiếp - đó là câu trả lời được chọn - nhưng sau đó bạn cần xây dựng đường tròn bezier tròn theo cách thủ công từ đường cong và đường và bạn cũng cần phải bù đắp cho thực tế là CoreGraphics sử dụng hệ tọa độ bản vẽ được lật ngược với UIKit.

+0

Điều này trong khi làm việc tốt, phản chiếu hình ảnh theo chiều ngang. tôi đã gỡ bỏ CGContextDrawImage ((ctx, imageRect, theImage.CGImage), và thay thế nó bằng một [drawImage drawInRect: CGRectMake (0,0, imageRect.size.width, imageRect.size.height)], và điều này giải quyết được vấn đề. – zachron

+0

@zachron cảm ơn sự điều chỉnh, tôi đã viết lại câu trả lời này để tránh toàn bộ CG nguyên bản.Điều đó có vẻ được đề xuất dựa trên việc đọc phần "Vẽ bằng Quartz và UIKit" trong http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html của Apple – algal

1

Rất đơn giản. self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width/2; self.profileImageView.clipsToBounds = YES;

Đối với mỗi chế độ xem, có thuộc tính lớp được nhóm. Vì vậy, dòng đầu tiên ở trên là đặt bán kính góc của đối tượng lớp (ví dụ: một thể hiện của lớp CALayer). Để tạo hình ảnh tròn từ một hình vuông, bán kính được đặt thành một nửa chiều rộng của UIImageView. Ví dụ: nếu chiều rộng của hình vuông là 100 pixel. Bán kính được đặt thành 50 pixel. Thứ hai, bạn phải thiết lập thuộc tính clipsToBounds thành YES để làm cho lớp hoạt động.

0

Building tắt của algal, đây là một vài phương pháp đó là tốt đẹp để đưa vào một thể loại UIImage:


- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius 
{ 
    CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height); 
    UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results 

    //create a bezier path defining rounded corners and use it for clippping 
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius]; 
    [path addClip]; 

    // draw the image into the implicit context 
    [self drawInRect:imageRect]; 

    // get image and cleanup 
    UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return roundedCornerImage; 
} 

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius 
{ 
    UIImage *image = nil; 
    if (size.width == 0 || size.height == 0) { 
     size = CGSizeMake(1.0, 1.0); 
    } 
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height); 
    UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size) 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    if (context) 
    { 
     CGContextSetFillColorWithColor(context, [color CGColor]); 
     if (radius > 0.0) { 
      //create a bezier path defining rounded corners and use it for clippping 
      UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; 
      [path addClip]; 
      CGContextAddPath(context, path.CGPath); 
     } 
     CGContextFillRect(context, rect); 
     image = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 
    } 
    return image; 
} 
Các vấn đề liên quan