将圆角添加到所有UIImageViews


78

我想在我的项目中的所有UIImageViews中添加一些圆角。我已经使代码工作了,但是必须将其应用于每个图像。我应该继承UIImageView来添加它吗?如果是这样,有人可以给我一些如何做的指示吗?

这是代码

- (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;
}

嗨,杰克-谢谢你,这正是我想要做的。当我尝试使用此功能时,出现错误“访问属性的未知'cornerRadius'组件”,而masksToBounds等也是如此。编译它们。上面的代码在iOS4.0上适合您吗?
本·克莱顿

20
您需要#import <QuartzCore / QuartzCore.h>
vodkhang 2010年

Answers:


25

您可以为UIImage使用类别,这是对Class进行子类化的一种替代方法,有时只需进行很小的更改就更容易。

例如,添加一个返回带有圆角属性集的UIImage的方法。

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

有关Objective-c类别的更多信息,请参见http://macdevelopertips.com/objective-c/objective-c-categories.html


优秀。非常感谢,我将实现UIImage类别-macdevelopertips.com上的教程非常有帮助。
杰克

4
我打算描述如何继承,但是我更喜欢这种方法。
Kendall Helmstetter Gelner 2010年

我很困惑 因此,所有UIImage的100%将具有此属性。为什么不子类化UIImage,类似UIFramedImage?
罗布


3
@Rob实际上,使用此方法时,0%的UIImage将具有圆角,直到将其更改为调用新方法为止。此解决方案不会覆盖现有方法(您不应这样做)。这是比子类更干净的解决方案,因为它不需要完整的子类(由于您没有向UIImage添加任何成员或新功能,所以可能会过分杀伤力),您所需要的只是一个不带代码重复的UIImage圆角。
贾森

114

选中此选项 -UIImage上的圆角

修改图层似乎是最好的方法。

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
谢谢。这基本上是我已经做过的,但是我使用了点符号来更改属性。我只是想知道是否容易将其添加到子类中,这样,如果我想更改半径,就不必更改每个实例了。
杰克

-1这并不是要回答这个问题,它是关于轻松地将相同的代码应用于每个UIImageView实例。
斯图尔特

16

除了子类化,您还可以通过UIImageView和CALayer上的简单类别来实现更强大的功能。

在UIImageView上创建一个类别,如下所示:

- (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];
    }
}

这将在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;
}

因此,这使您可以舍入任意UIRectCorner的角组合(请参阅),如果要以组样式放置图像,这尤其方便UITableView。但是,这样做有一个警告。由于我们没有子类化UIImageView,因此无法将任何代码注入layoutSubviews,这意味着遮罩层可能不正确。实际上,在配置单元格时,调用category方法时甚至不会设置图像视图的边界。因此,您需要在添加圆角之前确保已设置图像视图的边界(除非使用UIRectCornersAllCorners)。

这是执行此操作的一些代码:

        // 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];
        }

我有另一个类别,可以删除圆角-所有要做的就是删除所有蒙版并将设置cornerRadius为0。


1
很好的解决方案。但是我想知道是否创建所有视图都可以访问的类(如UILabel,UIButton,UIView等)会更好些?这是一种通用方法吗?
Borut Tomazin

1
没关系。我刚刚创建了可处理各种视图的UIView类别。谢谢!
Borut Tomazin,2012年

1
@BorutTomazin好主意-我当时在考虑YAGNI,但是将UIImageView类别移动到UIView将是一个很棒的实用程序功能。
丹尼尔·索普

1
正是我所做的。现在可以在其父视图为UIView的所有视图上使用...
Borut Tomazin 2012年

5

是的,您应该子类化UIImageView,并在整个项目中使用自定义子类。


1
谢谢,我认为那是最好的方法。您知道关于使用子类的任何优秀教程吗?我可以在接口构建器中使用此方法,还是应该用代码重写接口?
杰克

2
事实上,Martinj的回答上面可能更容易,不必到处使用自定义的子类,在Interface Builder等为您节省
雅各布博格

4

您可以对UIImageView进行子类化,然后如果实现其setNeedsDisplay方法,则圆角将对子类起作用。(不要忘记导入QuartzCore)

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

3
您一定不要这样做,setNeedsDisplay本质上是计划重新绘制,这就是目的。您必须使用init方法设置您的图层。
pronebird

3

试试这个,

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

这可能对您有帮助。


-1这不是试图回答问题。问题不是关于如何生成舍入的UIImageView(在问题的代码片段中成功完成),而是关于如何有效地重用该代码。
斯图尔特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.