2013-07-11 25 views
13

Tôi đang sử dụng UIImageView cho mỗi UITableViewCells làm hình thu nhỏ của mình. Mã của tôi sử dụng SDWebImage để lấy các hình ảnh đó một cách không đồng bộ từ chương trình phụ trợ của tôi và tải chúng vào và sau đó lưu vào bộ nhớ cache chúng. Điều này làm việc tốt.Sử dụng cornerRadius trên UIImageView trong UITableViewCell

My UIImageView là hình vuông 50x50, được tạo trong Trình tạo giao diện. Nền của nó là đục, màu trắng (giống như màu nền UITableViewCell của tôi, để thực hiện). Tuy nhiên, tôi muốn sử dụng các góc trơn tru để có tính thẩm mỹ tốt hơn. Nếu tôi làm điều này:

UIImageView *itemImageView = (UIImageView *)[cell viewWithTag:100]; 
    itemImageView.layer.cornerRadius = 2.5f; 
    itemImageView.layer.masksToBounds = NO; 
    itemImageView.clipsToBounds = YES; 

tableview My giảm khoảng 5-6 khung hình ngay lập tức, đóng nắp khoảng 56 FPS trong di chuyển nhanh (mà không quan trọng), nhưng khi tôi kéo và kéo điều khiển làm mới, nó chậm một chút và giảm xuống còn khoảng 40 FPS. Nếu tôi xóa dòng cornerRadius, tất cả đều ổn và không bị trễ. Điều này đã được thử nghiệm trên một chiếc iPod touch 5G sử dụng dụng cụ.

Có cách nào khác để tôi có thể làm tròn số UIImageView cho các ô của mình và không bị ảnh hưởng không? Tôi đã tối ưu hóa cellForRowAtIndexPath và tôi nhận được 56-59 FPS trong khi di chuyển nhanh chóng mà không cần cornerRadius.

Trả lời

30

Có, đó là vì cornerRadius và clipToBounds yêu cầu hiển thị trên màn hình, tôi khuyên bạn nên đọc những câu trả lời này từ một trong số question của tôi. Tôi cũng trích dẫn hai phiên WWDC mà bạn sẽ thấy.
Điều tốt nhất bạn có thể làm là lấy hình ảnh ngay sau khi tải xuống và trên một luồng khác gửi một phương thức làm tròn hình ảnh. Tốt hơn là bạn làm việc trên hình ảnh thay vì số lần xem hình ảnh.

// Get your image somehow 
UIImage *image = [UIImage imageNamed:@"image.jpg"]; 

// Begin a new image that will be the new image with the rounded corners 
// (here with the size of an UIImageView) 
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0); 

// Add a clip before drawing anything, in the shape of an rounded rect 
    [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
         cornerRadius:10.0] addClip]; 
// Draw your image 
[image drawInRect:imageView.bounds]; 

// Get the image, here setting the UIImageView image 
    imageView.image = UIGraphicsGetImageFromCurrentImageContext(); 

// Lets forget about that we were drawing 
    UIGraphicsEndImageContext(); 

Phương pháp nắm lấy here Bạn cũng có thể phân lớp các tableviewcell và ghi đè lên các phương pháp drawRect.
Cách bẩn nhưng rất hiệu quả là vẽ một mặt nạ trong photoshop với bên trong alpha và xung quanh màu sắc phù hợp của nền của ô và thêm một imageView khác, không đục với màu nền rõ ràng, trên hình có hình ảnh.

3

Có một giải pháp tốt khác cho việc này. Tôi đã làm nó một vài lần trong các dự án của tôi. Nếu bạn muốn tạo ra một góc tròn hoặc một cái gì đó khác bạn chỉ có thể sử dụng một hình ảnh bìa ở phía trước của hình ảnh chính của bạn.

Ví dụ: bạn muốn làm tròn các góc. Trong trường hợp này, bạn cần một lớp hình ảnh vuông với một vòng tròn cắt ra ở trung tâm.

Bằng cách sử dụng phương pháp này, bạn sẽ nhận được 60 khung hình/giây khi cuộn bên trong UITableView hoặc UICollectionView. Bởi vì phương pháp này không yêu cầu hiển thị trên màn hình để tùy chỉnh UIImageView (như hình đại diện và v.v ...).

4

Non giải pháp chặn

Là một theo dõi để phản ứng của Andrea, đây là một chức năng mà sẽ chạy mã của mình ở chế độ nền.

+ (void)roundedImage:(UIImage *)image 
      completion:(void (^)(UIImage *image))completion { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // Begin a new image that will be the new image with the rounded corners 
     // (here with the size of an UIImageView) 
     UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); 
     CGRect rect = CGRectMake(0, 0, image.size.width,image.size.height); 

     // Add a clip before drawing anything, in the shape of an rounded rect 
     [[UIBezierPath bezierPathWithRoundedRect:rect 
            cornerRadius:image.size.width/2] addClip]; 
     // Draw your image 
     [image drawInRect:rect]; 

     // Get the image, here setting the UIImageView image 
     UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext(); 

     // Lets forget about that we were drawing 
     UIGraphicsEndImageContext(); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      if (completion) { 
       completion(roundedImage); 
      } 
     }); 
    }); 
} 
0

Swift 3 phiên bản của câu trả lời thedeveloper3124 của

func roundedImage(image: UIImage, completion: @escaping ((UIImage?)->(Void))) { 
    DispatchQueue.global().async { 
     // Begin a new image that will be the new image with the rounded corners 
     // (here with the size of an UIImageView) 
     UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale) 
     let rect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) 

     // Add a clip before drawing anything, in the shape of an rounded rect 
     UIBezierPath(roundedRect: rect, cornerRadius: image.size.width/2).addClip() 

     // Draw your image 
     image.draw(in: rect) 

     // Get the image, here setting the UIImageView image 
     guard let roundedImage = UIGraphicsGetImageFromCurrentImageContext() else { 
      print("UIGraphicsGetImageFromCurrentImageContext failed") 
      completion(nil) 
      return 
     } 

     // Lets forget about that we were drawing 
     UIGraphicsEndImageContext() 

     DispatchQueue.main.async { 
      completion(roundedImage) 
     } 
    } 
} 
Các vấn đề liên quan