2013-07-11 10 views
13

私はそれぞれUITableViewCellsのためにUIImageViewをサムネイルとして使用しています。私のコードでは、SDWebImageを使用してバックエンドの画像を非同期に取得し、ロードしてからキャッシュします。これはうまくいきます。UITableViewCellのUIImageViewでcornerRadiusを使用

私のUIImageViewは、Interface Builderで作成された50x50の正方形です。その背景は不透明で、白い色です(パフォーマンスのために私のUITableViewCell背景色と同じです)。しかし、私はより良い美学のために滑らかなコーナーを使用したいと思います。

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

私のテーブルビューは(大丈夫です)高速スクロール時の56 FPSについてキャッピング、すぐに周り5-6フレームを廃棄しますが、私はドラッグして、リフレッシュ制御を引くとき、それは少し遅れると:私はこれを行う場合約40FPSに低下します。 cornerRadius行を削除しても、すべて問題はなく、遅延はありません。これはInstrumentsを使用してiPod touch 5Gでテストされています。

私のセルには丸みを帯びたUIImageViewがあり、パフォーマンスが低下しない他の方法はありますか?私はすでにcellForRowAtIndexPathを最適化していましたが、高速でスクロールしながら、cornerRadiusの56-59 FPSを得ました。

答えて

30

はい、cornerRadiusとclipToBoundsにはオフスクリーンレンダリングが必要なので、これらの回答を私のquestionからお読みください。私はまた、あなたが見るはずの2つのWWDCセッションを引用します。
あなたができる最良のことは、ダウンロードされた直後のイメージを取得し、別のスレッドでイメージを丸くするメソッドをディスパッチすることです。イメージビューの代わりにイメージで作業することをお勧めします。

// 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(); 

方法は、あなたがまたtableviewcellをサブクラス化のdrawRectメソッドをオーバーライドすることができhere をつかみました。
汚れているが非常に効果的な方法は、アルファの内側とセルの背景の色の周りにあるフォトショップでマスクを描画し、画像がある背景に透明な背景色で不透明ではない別のimageViewを追加します。

3

これには別の良い解決策があります。私は自分のプロジェクトで数回それをやった。丸みを帯びたコーナーなどを作成したい場合は、メイン画像の前に表紙画像を使用します。

たとえば、角を丸くしたいとします。この場合、中央に切り抜かれた円を持つ正方形の画像レイヤーが必要です。

この方法を使用すると、UITableViewまたはUICollectionViewにスクロールすると60fpsになります。このメソッドは、アバターなどのようにUIImageViewのカスタマイズのためのオフスクリーンレンダリングを必要としないためです。

4

非ブロッキング溶液

フォローアップアンドレアの対応については

は、ここではバックグラウンドで自分のコードを実行する関数です。

+ (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

スウィフト3 thedeveloper3124の答えのバージョン

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) 
     } 
    } 
} 
関連する問題