8

I have a tableview with custom cells which are built from storyboard with an identifier using AutoLayout.

One of the subviews needs to be round (layer.cornerRadius = width/2), it is a square in the beginning.

I have tried in layoutSubviews() but it seems to be called before AutoLayout changes its size... same thing for didMoveToSuperview()

Where is the proper function to update things like this to my subviews after AutoLayout has changed their sizes?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("cell_small") as! Cell
    ...
    return cell
}

// In Cell

override func layoutSubviews() {
    rankLabel.layer.cornerRadius = rankLabel.bounds.width/2
    rankLabel.layer.masksToBounds = true
}

override func didMoveToSuperview() {
    rankLabel.layer.cornerRadius = rankLabel.bounds.width/2
    rankLabel.layer.masksToBounds = true
}

Result:

Arbitur
  • 38,684
  • 22
  • 91
  • 128
  • have you tried in cellForRowAtIndexPath method ? – Muhammad Adnan May 20 '15 at 11:57
  • cellForRowAtIndexPath is called before layout, see my answer below, you can use willDisplayCell – Christian May 20 '15 at 12:02
  • use rankLabel.clipsToBounds=YES; – Muhammad Adnan May 20 '15 at 12:03
  • if I print out rankLabel's size it is the wrong size for everything Ive tried. But If I swipe the tableview then it calls the updatefunctions and the size is right. – Arbitur May 20 '15 at 12:07
  • Ive had lots of problem with autolayout before if I want a round subview... – Arbitur May 20 '15 at 12:13
  • I guess everything is right. Its just the width of the UILabel that might cause this problem. Do check width of the the label by putting break point in layoutSubviews() – BangOperator May 21 '15 at 07:11
  • @somexyz Its actually a label with backgroundcolor and cornerRadius – Arbitur May 21 '15 at 07:12
  • Try using this "rankLabel.layer.cornerRadius = rankLabel.bounds.height/2" instead of "rankLabel.layer.cornerRadius = rankLabel.bounds.width/2" – BangOperator May 21 '15 at 07:13
  • @somexyz Ive already tried it. I have width and height constraints on it, the label without these constraints wants to be bigger snd the problem is that att the point when the class reaches layoutSubviews() autolayout havny changed its size yet. – Arbitur May 21 '15 at 07:16
  • Same problem here, any updates? I added that 2 lines of code in `- (void) layoutSubviews`. It worked, but at a while after the cell has been displayed so that there is an obvious shape change. – JonSlowCN Aug 13 '15 at 10:00
  • You have to subclass every view you want to change the shape of and then inside its layoutSubviews you do the shape. – Arbitur Aug 13 '15 at 11:01
  • @LordSpark Check my answer I just made. – Arbitur Aug 13 '15 at 11:09
  • @Arbitur Thanks a lot! – JonSlowCN Aug 14 '15 at 00:55
  • Check this one **working** in my case .. http://stackoverflow.com/questions/32362934/how-to-keep-a-round-imageview-round-using-auto-layout/43998774#43998774 – Mr.Javed Multani May 16 '17 at 10:28

6 Answers6

14

What I ended up doing was making a class called RoundView

class RoundView:UIView {
    override func layoutSubviews() {
        super.layoutSubviews()

        self.layer.cornerRadius = self.bounds.width/2
        self.layer.masksToBounds = true
    }
}

And then I apply it to every view I need to be round. So in Storyboard I add RoundView to Custom Class.

What was happening was that if you look inside the source of the storyboard (XML) every view had the size of the whole screen, you can look inside your own SB code. So by trying to add a corner radius equal to the width/2 inside its parent layoutSubviews() that subview hasn't got its frame set correctly. So the corner radius got the value of 320/2 instead of 50/2, thats why it got misshaped.

Arbitur
  • 38,684
  • 22
  • 91
  • 128
3

1.Create a custom class of UIView/category

#import <UIKit/UIKit.h>
@interface RoundView : UIView

@end
#import "RoundView.h"

2.Add layoutSubviews method and set corner radius.

@implementation RoundView

-(void)layoutSubviews{

[super layoutSubviews];

self.layer.cornerRadius = self.bounds.size.width/2;

self.layer.masksToBounds = true;

}

3.Make your UIView as a subclass of RoundView and run the application, you can see circle view.

User42
  • 970
  • 1
  • 16
  • 27
Anisha V
  • 61
  • 4
1

Try subclassing UITableViewCell like this,

@interface RoundingCell : UITableViewCell

@property (nonatomic,weak) IBOutlet UILabel * someLabel;

@end

@implementation RoundingCell

-(void)layoutSubviews
{
    [super layoutSubviews];
    self.someLabel.layer.cornerRadius = CGRectGetHeight(self.someLabel.bounds)/2;
    self.someLabel.layer.masksToBounds = YES;
}

@end

And Use this as the class of the desired cell, along with IBOutlet connections.

BangOperator
  • 4,377
  • 2
  • 24
  • 38
1

I had the same issue with my imageview so i resolved it by sub-classing UIImageView.

@interface MyImageView : UIImageView

@end

@implementation MyImageView

-(void)layoutSubviews
{
    [super layoutSubviews];    
    self.layer.cornerRadius = self.bounds.size.width / 2.0;
}
@end
Usman
  • 457
  • 4
  • 8
0

It's strange, I make my round cells just by using your code. (and I also use auto layout).

The only difference is, I use .frame and not .bounds (divided by 2). Have you tried that?

Otherwise you can use a custom cell and in the -awakeFromNib set rounding the same way, so you don't have to do it in each cell.

Gil Sand
  • 5,802
  • 5
  • 36
  • 78
  • I do have it structured like this: contentView->UIView->UILabel So maybe i need to subclass that UIView and in awakeFromNib or layoutSubViews make UILabel round there? – Arbitur May 21 '15 at 08:12
  • if you have a Label in a view, then you must have `IBOutlets` that you can use. Something like `cell.myView.layer.frame.width/2` should do the job. Not forgetting the mask of course. – Gil Sand May 21 '15 at 08:17
-1

You have two options:

  1. Create a custom Class YourCell and add your code to the initWithCoder-Method
  2. Add a method to your ViewController

like following

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

and change it inside there. To access the cell you call

[(YourCell *)cell view]....
Christian
  • 4,596
  • 1
  • 26
  • 33
  • Neither worked :( And I dont think iniWithCoder would ever work because it is called before anything else :P – Arbitur May 20 '15 at 12:05