2010-01-31 20 views
78

Tôi muốn thêm một số góc được làm tròn cho tất cả các UIImageViews trong dự án của tôi. Tôi đã có mã làm việc, nhưng phải áp dụng nó cho mọi hình ảnh; sao tôi nên phân lớp UIImageView để thêm cái này? Nếu có, ai đó có thể cho tôi một số gợi ý về cách làm điều này không?Thêm các góc tròn cho tất cả các UIImageViews

Đây là mã

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSString *mainpath = [[NSBundle mainBundle] bundlePath]; 
    welcomeImageView.image = [UIImage imageWithContentsOfFile:[mainpath stringByAppendingString:@"/test.png"]]; 
    welcomeImageView.layer.cornerRadius = 9.0; 
    welcomeImageView.layer.masksToBounds = YES; 
    welcomeImageView.layer.borderColor = [UIColor blackColor].CGColor; 
    welcomeImageView.layer.borderWidth = 3.0; 
    CGRect frame = welcomeImageView.frame; 
    frame.size.width = 100; 
    frame.size.height = 100; 
    welcomeImageView.frame = frame; 
} 
+0

Xin chào Jack - cảm ơn vì điều này, đó chính là điều tôi muốn làm. Khi tôi cố gắng sử dụng điều này tôi nhận được một lỗi 'truy cập không rõ' cornerRadius 'thành phần của một tài sản', và tương tự cho masksToBounds vv Oddly tính năng mã cảm giác trong xcode helpfully điền vào các thuộc tính cho tôi, nhưng trình biên dịch sẽ không biên dịch chúng. Mã trên có hoạt động cho bạn trên iOS4.0 không? –

+20

Bạn cần # import vodkhang

Trả lời

25

Bạn có thể sử dụng danh mục cho UIImage là một cách thay thế để phân lớp một Lớp và đôi khi dễ dàng hơn cho những thay đổi nhỏ.

ví dụ: thêm phương thức trả về UIImage với tập hợp thuộc tính góc tròn.

+(UIImage *)imageWithContentsOfFile:(NSString *)file cornerRadius:(NSInteger)... 

biết thêm về loại Objective-C có thể được tìm thấy http://macdevelopertips.com/objective-c/objective-c-categories.html

+0

Tuyệt vời. Cảm ơn rất nhiều, tôi sẽ triển khai một danh mục UIImage - hướng dẫn trên macdevelopertips.com rất hữu ích. – Jack

+4

Tôi sẽ mô tả làm thế nào để phân lớp nhưng tôi thích cách tiếp cận này nhiều hơn nữa. –

+0

Tôi đang bối rối. Vì vậy, 100% của tất cả các UIImages sẽ có điều này. Tại sao không phân lớp UIImage, một cái gì đó giống như UIFramedImage? – Rob

5

Có, bạn nên phân lớp UIImageView, và sử dụng phân lớp tùy chỉnh của bạn trong suốt dự án của bạn.

+1

Cảm ơn, tôi nghĩ đó sẽ là cách tốt nhất. Bạn có biết bất kỳ hướng dẫn tốt nào về việc sử dụng các lớp con không? Tôi có thể sử dụng phương pháp này với trình tạo giao diện hay tôi nên viết lại giao diện của mình bằng mã? – Jack

+2

Thực ra, câu trả lời của Martinj ở trên có lẽ dễ dàng hơn, giúp bạn không phải sử dụng lớp con tùy chỉnh ở mọi nơi, trong Bộ dựng giao diện, v.v. –

114

Kiểm tra này - Rounded Corners on UIImage

Việc sửa đổi lớp có vẻ là cách tốt nhất.

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]; 
+1

Cảm ơn. Đây chính là những gì tôi đã làm, tuy nhiên tôi đã sử dụng ký pháp chấm để thay đổi các thuộc tính. Tôi chỉ tự hỏi nếu có một cách dễ dàng là để thêm này vào một phân lớp để nếu tôi muốn thay đổi bán kính tôi sẽ không phải thay đổi mọi trường hợp này. – Jack

+0

-1 Điều này không cố gắng trả lời câu hỏi, đó là về việc dễ dàng áp dụng cùng một mã cho mỗi cá thể 'UIImageView'. – Stuart

+0

Bạn cần nhập QuartzCore.framework –

16

Thay vì subclassing, bạn có thể đạt được chức năng mạnh mẽ hơn thông qua loại đơn giản trên UIImageView và CALayer.

Tạo một thể loại trên UIImageView như thế này:

- (void)maskRoundCorners:(UIRectCorner)corners radius:(CGFloat)radius { 
    // To round all corners, we can just set the radius on the layer 
    if (corners == UIRectCornerAllCorners) { 
     self.layer.cornerRadius = radius; 
     self.layer.masksToBounds = YES; 
    } else { 
     // If we want to choose which corners we want to mask then 
     // it is necessary to create a mask layer. 
     self.layer.mask = [CALayer maskLayerWithCorners:corners radii:CGSizeMake(radius, radius) frame:self.bounds]; 
    } 
} 

Điều này đòi hỏi một phương pháp loại trên CALayer:

+ (id)maskLayerWithCorners:(UIRectCorner)corners radii:(CGSize)radii frame:(CGRect)frame { 

    // Create a CAShapeLayer 
    CAShapeLayer *mask = [CAShapeLayer layer]; 

    // Set the frame 
    mask.frame = frame; 

    // Set the CGPath from a UIBezierPath 
    mask.path = [UIBezierPath bezierPathWithRoundedRect:mask.bounds byRoundingCorners:corners cornerRadii:radii].CGPath; 

    // Set the fill color 
    mask.fillColor = [UIColor whiteColor].CGColor; 

    return mask; 
} 

Vì vậy, điều này cho phép bạn để làm tròn kết hợp bất kỳ (xem UIRectCorner) của góc, đặc biệt hữu ích nếu bạn muốn đặt hình ảnh theo kiểu nhóm UITableView. Có một báo trước khi thực hiện điều này tuy nhiên. Bởi vì chúng tôi đã không phân loại UIImageView, chúng tôi không thể tiêm bất kỳ mã nào vào layoutSubviews, điều đó có nghĩa là lớp mặt nạ có thể không chính xác. Trong thực tế, khi định cấu hình ô, các giới hạn của chế độ xem hình ảnh thậm chí sẽ không được đặt khi bạn gọi phương thức danh mục. Do đó, bạn cần đảm bảo giới hạn của chế độ xem hình ảnh được đặt trước khi thêm các góc tròn (trừ khi sử dụng UIRectCornersAllCorners).

Dưới đây là một số mã mà thực hiện điều này:

 // Perform corner rounding 
     UIRectCorner corners = !UIRectCornerAllCorners; 
     if (indexPath.row == 0) 
      corners = UIRectCornerTopLeft; 
     if (indexPath.row == numberOfRowsInTheTable) 
      corners |= UIRectCornerBottomLeft; 

     if (corners > 0) { 
      cell.imageView.bounds = CGRectMake(0.f, 0.f, [self.tableView rowHeight], [self.tableView rowHeight]); 
      [cell.imageView maskRoundCorners:corners radius:10.f]; 
     } else { 
      [cell.imageView removeRoundCornersMask]; 
     } 

tôi có một loại mà loại bỏ các góc tròn - tất cả điều đó không được loại bỏ bất kỳ mặt nạ và thiết lập cornerRadius để 0.

+1

Giải pháp tuyệt vời. Nhưng tôi tự hỏi nếu nó sẽ không được tốt hơn để tạo ra lớp học mà tất cả các xem có thể truy cập nó như UILabel, UIButton, UIView, vv - loại một phương pháp phổ quát? –

+1

Đừng bận tâm. Tôi vừa tạo danh mục UIView xử lý tất cả các loại chế độ xem. Cảm ơn! –

+1

@BorutTomazin tuyệt vời nghĩ - Tôi đã suy nghĩ YAGNI, nhưng di chuyển các thể loại UIImageView để UIView sẽ là một chức năng tiện ích nhỏ tuyệt vời. –

4

Bạn có thể phân lớp UIImageView và sau đó nếu bạn triển khai phương thức setNeedsDisplay, các góc tròn sẽ hoạt động trên các lớp con. (Đừng quên để nhập khẩu QuartzCore)

-(void)setNeedsDisplay { 
    self.layer.cornerRadius = 5; 
    self.layer.masksToBounds = YES; 
    [self.layer setBorderColor:[[UIColor whiteColor] CGColor]]; 
    [self.layer setBorderWidth: 2.0]; 
} 
+2

Bạn không được làm điều này, setNeedsDisplay về cơ bản lịch trình repaint, và đó là mục đích của nó. Bạn phải thiết lập lớp của bạn trong phương thức init. – Andy

3

Hãy thử điều này,

coverImage.image = [UIImage imageWithContentsOfFile:@"coverImage.png"]; 
coverImage.layer.masksToBounds = YES; 
coverImage.layer.cornerRadius = 10.0; 
coverImage.layer.borderWidth = 1.0; 
coverImage.layer.borderColor = [[UIColor brown] CGColor]; 

này có thể giúp bạn.

+0

-1 Điều này không cố gắng trả lời câu hỏi. Câu hỏi không phải là về cách tạo ra một 'UIImageView' tròn (điều này được thực hiện thành công trong đoạn mã của câu hỏi), nhưng về cách sử dụng lại mã đó một cách hiệu quả. – Stuart