【问题标题】:Circular UIImageView in UITableView without performance hit?UITableView 中的圆形 UIImageView 没有性能影响?
【发布时间】:2013-07-17 07:31:11
【问题描述】:

我的每个UITableView 单元格上都有一个UIImageView,用于显示远程图像(使用SDWebImage)。我对图像视图做了一些QuartzCore 图层样式,例如:

UIImageView *itemImageView = (UIImageView *)[cell viewWithTag:100];
    itemImageView.layer.borderWidth = 1.0f;
    itemImageView.layer.borderColor = [UIColor concreteColor].CGColor;
    itemImageView.layer.masksToBounds = NO;
    itemImageView.clipsToBounds = YES;

所以现在我有一个带有浅灰色边框的 50x50 正方形,但我想让它变成圆形而不是正方形。应用程序Hemoglobe 在表格视图中使用圆形图像,这就是我想要实现的效果。但是,我不想使用cornerRadius,因为这会降低我的滚动 FPS。

这里是Hemoglobe 显示循环UIImageViews

有什么办法可以达到这个效果吗?谢谢。

【问题讨论】:

  • 不是cornerRadius 影响性能,maskToBounds/clipsToBounds 是问题

标签: ios objective-c uitableview uiimageview


【解决方案1】:

对于圆形图像视图,请使用以下代码。

self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
self.imageView.clipsToBounds = true

不要忘记在 UIView 的 viewDidLayoutSubviews 方法中更改cornerRadius。

例子:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}

【讨论】:

    【解决方案2】:

    如果使用一些自动布局和不同的单元格高度,你最好这样做:

       override func layoutSubviews() {
            super.layoutSubviews()
            logo.layer.cornerRadius = logo.frame.size.height / 2;
            logo.clipsToBounds      = true;
        }
    

    【讨论】:

      【解决方案3】:

      这是一个更新的快速方法,使用 IBDesignable 和 IBInspectable 来继承 UIImageView

      @IBDesignable class RoundableUIImageView: UIImageView {
          private var _round = false
          @IBInspectable var round: Bool {
              set {
                  _round = newValue
                  makeRound()
              }
              get {
                  return self._round
              }
          }
          override internal var frame: CGRect {
              set {
                  super.frame = newValue
                  makeRound()
              }
              get {
                  return super.frame
              }
      
          }
      
          private func makeRound() {
              if self.round == true {
                  self.clipsToBounds = true
                  self.layer.cornerRadius = (self.frame.width + self.frame.height) / 4
              } else {
                  self.layer.cornerRadius = 0
              }
          }
      
          override func layoutSubviews() {
                  makeRound()
          }
      }
      

      【讨论】:

      • 我必须添加以下代码才能使它对我有用(在表格视图单元格内): override func layoutSubviews() { makeRound() }
      • + 1 代表@herbert。当我在类中覆盖 layoutSubviews 时,它完全对我有用,你应该更新代码
      • 谢谢!!我终于做了这个(子类,但在 Objective-C 中)来处理一些循环的 UIImageViews,这些 UIImageViews 只是不会停留。
      【解决方案4】:

      在 Swift 中将此扩展用于 CircularImageView 或 RoundedImageView :

      extension UIView {
      
          func circular(borderWidth: CGFloat = 0, borderColor: UIColor = UIColor.whiteColor()) {
              let radius = CGRectGetWidth(self.bounds) / 2
              self.layer.cornerRadius = radius
              self.layer.masksToBounds = true
      
              self.layer.borderWidth = borderWidth
              self.layer.borderColor = borderColor.CGColor
          }
      
          func roundedCorner(borderWidth: CGFloat = 0, borderColor: UIColor = UIColor.whiteColor()) {
              let radius = CGRectGetWidth(self.bounds) / 2
              self.layer.cornerRadius = radius / 5
              self.layer.masksToBounds = true
      
              self.layer.borderWidth = borderWidth
              self.layer.borderColor = borderColor.CGColor
          }
      
      }
      

      用法:

      self.ImageView.circular()
      self.ImageView.roundedCorner()
      

      【讨论】:

        【解决方案5】:

        将 UIImageView 的高度和宽度设置为相同,例如:Height=60Width = 60,然后cornerRadius 应该正好是一半。我将它保持在 30 在我的情况下。它适用于我。

         self.imageView.layer.cornerRadius = 30;
         self.imageView.layer.borderWidth = 3;
         self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
         self.imageView.layer.masksToBounds = YES;
        

        【讨论】:

          【解决方案6】:

          Swift 中使用extension 的可用解决方案:

          extension UIView{
            func circleMe(){
                let radius = CGRectGetWidth(self.bounds) / 2
                self.layer.cornerRadius = radius
                self.layer.masksToBounds = true
            }
          }
          

          用法:

          self.venueImageView.circleMe()
          

          【讨论】:

          • 将扩展名应用到UIImageView 不是更好吗?此代码有效,但它使扩展对任何 UIView 对象都是通用的。
          • UIImageView 已经从 UIView 扩展而来。在某些情况下,您可能需要圈出一些UIViews,因此此方法适用于所有人。
          【解决方案7】:

          在 swift 中,在您的 viewDidLoad 方法中,使用 userImage 出口:

          self.userImage.layer.borderWidth = 1;
          self.userImage.layer.borderColor = UIColor.whiteColor().CGColor;
          self.userImage.layer.cornerRadius = self.userImage.frame.size.width / 2;
          self.userImage.clipsToBounds = true;
          

          【讨论】:

            【解决方案8】:

            我使用圆形图像视图类... 所以我只是用它来代替 UIImageView,没有什么可调整的……

            这个类还在圆周围绘制一个可选的边框。圆形图片周围通常有边框。

            它不是UIImageView的子类,因为UIImageView有自己的渲染机制,不调用drawRect方法..

            界面:

            #import <UIKit/UIKit.h>
            
            @interface MFRoundImageView : UIView
            
            @property(nonatomic,strong) UIImage* image;
            
            @property(nonatomic,strong) UIColor* strokeColor;
            @property(nonatomic,assign) CGFloat strokeWidth;
            
            @end
            

            实施:

            #import "MFRoundImageView.h"
            
            
            @implementation MFRoundImageView
            
            -(void)setImage:(UIImage *)image
            {
                _image = image;
                [self setNeedsDisplay];
            }
            
            -(void)setStrokeColor:(UIColor *)strokeColor
            {
                _strokeColor = strokeColor;
                [self setNeedsDisplay];
            }
            
            -(void)setStrokeWidth:(CGFloat)strokeWidth
            {
                _strokeWidth = strokeWidth;
                [self setNeedsDisplay];
            }
            
            - (void)drawRect:(CGRect)rect {
                CGContextRef ctx = UIGraphicsGetCurrentContext();
                CGPathRef path = CGPathCreateWithEllipseInRect(self.bounds, NULL);
                CGContextAddPath(ctx, path);
                CGContextClip(ctx);
                [self.image drawInRect:rect];
            
                if ( ( _strokeWidth > 0.0f ) && _strokeColor ) {
                    CGContextSetLineWidth(ctx, _strokeWidth*2); // Half border is clipped
                    [_strokeColor setStroke];
                    CGContextAddPath(ctx, path);
                    CGContextStrokePath(ctx);
                }
                CGPathRelease(path);
            }
            
            @end
            

            【讨论】:

              【解决方案9】:

              只需将cornerRadius 设置为宽度或高度的一半(假设您的对象的视图是正方形的)。

              例如,如果您的对象视图的宽度和高度均为 50:

              itemImageView.layer.cornerRadius = 25;
              

              更新 - 正如用户 atulkhatri 指出的那样,如果您不添加,它将无法工作:

              itemImageView.layer.masksToBounds = YES;
              

              【讨论】:

              • 为什么这是最好的答案?嗯,我不这么认为。使用cornerRadius 会导致滚动视图的性能下降,尤其是在iPhone4 设备中。
              • 我喜欢'将cornerRadius设置为宽度或高度的一半',但不要忘记添加'itemImageView.layer.masksToBounds = YES;'否则它将无法正常工作。
              • 顺便说一句,正如 Danny Xu 所说,它会降低 tableview 滚动性能,所以应该避免在 tableview 单元格中。
              • 这应该可以解决您的 tableview 滚动性能问题。 self.imageView.layer.shouldRasterize = YES; self.imageView.layer.rasterizationScale = [UIScreen mainScreen].scale;
              • 对于 Swift3:itemImageView.layer.masksToBounds = true;
              【解决方案10】:

              添加边框

              self.ImageView.layer.borderWidth = 3.0f;
              
              self.ImageView.layer.borderColor = [UIColor whiteColor].CGColor;
              

              圆形

              self.ImageView.layer.cornerRadius = self.ImageView.frame.size.width / 2;
              self.ImageView.clipsToBounds = YES;
              

              参考这个链接

              http://www.appcoda.com/ios-programming-circular-image-calayer/

              【讨论】:

                【解决方案11】:

                可以,可以给layer.cornerRadius(需要加 #import &lt;QuartzCore/QuartzCore.h&gt;)
                用于创建循环任何控件,但在您的情况下,而不是设置 layerUIImageView 它是 将图像创建为圆形并将其添加到 UIImageView 的最佳方法是 backGroundColorClearColor

                另请参考这两个代码源。

                https://www.cocoacontrols.com/controls/circleview

                https://www.cocoacontrols.com/controls/mhlazytableimages

                这可能对您的情况有所帮助:

                【讨论】:

                • 最后,我认为@iPatel 是唯一关心这里表现的人。如果您希望在滚动时获得高性能,请小心使用cornerRadius。
                • 我有点困惑...你为什么要发布圆视图项目链接?这与问题无关,也与您给出的答案无关。
                • @iPatel - 更新:第二个链接已被作者弃用,无法再下载。
                【解决方案12】:

                如果您在纯色背景上显示图像,一个简单的解决方案是使用中间带有透明圆圈的叠加图像。

                这样您仍然可以使用方形图像并在其上方添加圆形图像以获得圆形效果。

                如果您不需要处理图像或在复杂的背景颜色上显示它们,这可能是一个不会影响性能的简单解决方案。

                【讨论】:

                • 不,我不知道。这只是简单的加载、自动缓存(方形缩略图)和显示。
                • 这真的很有效。我以前用过这种棘手的方法。但它现在不适合我的新版本应用程序。
                【解决方案13】:

                使用此代码.. 这会很有帮助..

                    UIImage* image = ...;
                    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:50.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();
                

                它对我来说很好用。 :)

                【讨论】:

                • 使用这段代码真的很简单!!谢谢@Shivam
                【解决方案14】:

                使用下面的 SO 链接创建圆形图像视图非常简单,只需为您的表格视图自定义单元格,而不是在 cellForRowAtIndexPath 方法中分配所有内容。

                how to make button round with image background in IPhone?

                上面的链接为您提供了按钮示例,只需将其用于您的图像视图。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-05-08
                  • 2020-03-27
                  • 1970-01-01
                  • 2023-03-17
                  • 2013-08-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-09-05
                  相关资源
                  最近更新 更多