How to change UITableViewCell Image to Circle in UITableView
Asked Answered
E

11

22

My code works for the most part.

  • The issue I am having is the images start out as square, and change to circle when I scroll the table or refresh it.

What am I missing?

Here's my code:

    cell.imageView.layer.cornerRadius = cell.imageView.frame.size.width / 2.0;
    cell.imageView.layer.borderWidth = 3.0;
    cell.imageView.layer.borderColor = [UIColor colorWithRed:157.0/255.0 green:34.0/255.0 blue:53.0/255.0 alpha:1.0]
    .CGColor;
    cell.imageView.clipsToBounds = YES;

    NSDictionary *tweet = (self.results)[indexPath.row];
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
    
        NSString * imageString = [tweet valueForKeyPath:@"user.profile_image_url"];
        NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:imageString]];
        
        if (imageData != nil)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                cell.imageView.image = [UIImage imageWithData: imageData];

                [cell setNeedsLayout];
            });
        }
    });

EDIT ---- The code is in cellForRowAtIndexPath

  • Right when I launch the app the cell images are square. If I pullToRefresh the change to round or if I start scrolling the table they change to round.

EDIT TWO

Another issue I am seeing is the images change as I scroll.

How do I prevent this?

Empiric answered 28/4, 2014 at 20:37 Comment(6)
Where do you have this code?Impugn
The code you posted indicates that you want the image views to be round, correct? So the problem is that they don't appear round initially?Selfmortification
it's in cellForRowAtIndexPath. Yes, I want them to always be round, but they start as square and update to round if I refresh or scroll.Empiric
Every thing here depends upon the row height. So if you have row height as 100, just make the cell.imageView.layer.cornerRadius=50; That means always the rowHeight/2.Dian
I get the same problem.Sometimes UIImageView is circle, sometimes not.But I find if your Image height and width equal to cell's height, it will work.Seine
Hey did you find any solution for this?Idol
I
10

In order if anyone having this problem, here is the solution in

Swift

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:ContactCellTableViewCell? = tableView.dequeueReusableCellWithIdentifier("contactCell", forIndexPath: indexPath) as? ContactCellTableViewCell



    var contact : ContactStruct
    image = searchResults[indexPath.row]
    let newImage = resizeImage(image, toTheSize: CGSizeMake(70, 70))
    var cellImageLayer: CALayer?  = cell?.imageView.layer
    cellImageLayer!.cornerRadius = 35
    cellImageLayer!.masksToBounds = true
    cell?.imageView.image = newImage


    return cell!
}

As you might noticed the 35 hardcode is basically half of the image size which is 70 in here. And here is the resize function:

func resizeImage(image:UIImage, toTheSize size:CGSize)->UIImage{


    var scale = CGFloat(max(size.width/image.size.width,
        size.height/image.size.height))
    var width:CGFloat  = image.size.width * scale
    var height:CGFloat = image.size.height * scale;

    var rr:CGRect = CGRectMake( 0, 0, width, height);

    UIGraphicsBeginImageContextWithOptions(size, false, 0);
    image.drawInRect(rr)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext();
    return newImage
}

Note: I am using a custom cell class as below:

import UIKit

class ContactCellTableViewCell: UITableViewCell {

    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var contactImage: UIImageView!
    @IBOutlet weak var phoneLabel: UILabel!




    override func awakeFromNib() {
        super.awakeFromNib()

    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

It really took me a while to figure this one out. The images become rounded after scrolling at first, but now using this code you are going to have the rounded images inside the cell from beginning. Hope it helped anyone.

Ignazio answered 30/10, 2014 at 14:48 Comment(0)
N
8

Try this in override-

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    // image Width(84) / 2 = 42
            cell.CellImage.layer.cornerRadius = 42.0
            cell.CellImage.layer.masksToBounds = true
         //or   

        cell.CellImage.layer.cornerRadius = cell.CellImage.frame.width / 2
        cell.CellImage.clipsToBounds = true
}
Nu answered 3/6, 2015 at 19:4 Comment(0)
S
5

Most likely the cell's frame (and hence the imageView's frame) isn't set the very first time the cell is created. So setting the imageView's layer's cornerRadius based on that initial frame doesn't work. The best solution is to implement the tableView:willDisplayCell:forRowAtIndexPath: delegate method and set the layer there:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.imageView.layer.cornerRadius = cell.imageView.frame.size.width / 2.0;
}
Selfmortification answered 28/4, 2014 at 21:20 Comment(6)
still start as square when I implement thisEmpiric
What are you getting for cell.imageView and cell.imageView.frame?Selfmortification
cell.imageView: <UIImageView: 0xa479fe0; frame = (0 0; 0 0); clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0xa47c4a0>> and cell.imageView.frame: 0.000000Empiric
when I refresh: cell.imageView: <UIImageView: 0xa5a7890; frame = (15 30; 48 48); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xa5a7910>> and cell.imageView.frame: 4294968343.000000Empiric
You could set a dummy image to new cells that don't yet have an image. This should initialize the imageView frame so the cornerRadius calculation works as expected.Selfmortification
I'm loading the images asynchronously. Could it be that cells near the bottom haven't gotten images yet and that's why they appear as squares until I scroll?Empiric
I
2

Create a custom cell, and add an image view (with an IBOutlet), sized and positioned however you want (the outlet is "iv" in my example below). Put the code to make image view round in the awakeFromNib method (assuming your cell is created in a nib or storyboard).

-(void)awakeFromNib {
    self.iv.layer.cornerRadius = self.iv.frame.size.width / 2.0;
    self.iv.layer.borderWidth = 3.0;
    self.iv.layer.borderColor = [UIColor colorWithRed:157.0/255.0 green:34.0/255.0 blue:53.0/255.0 alpha:1.0].CGColor;
    self.iv.clipsToBounds = YES;
}
Impugn answered 28/4, 2014 at 21:45 Comment(3)
Cell's already come with an imageView property. The issue so far is that the default imageView's frame isn't set until it gets an image.Selfmortification
@rmaddy, yeah, I'm aware that cells come with an image view property. It works the way I did it here with no image present. Also, I'm generally not a fan of setting up things that are not indexPath dependent in the table view's delegate/data source. I think those things should belong to the cell, so that's why I suggested this approach.Impugn
This works great but only if you explicitly specify a height for the imageView in the storyboard.Lustful
G
2

Its simple..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell.ImageView.layer.cornerRadius = 150.0f;
    cell.ImageView.layer.borderWidth = 2.0f;
    cell.ImageView.layer.borderColor = [UIColor blackColor].CGColor;
    cell.ImageView.clipsToBounds = YES;
}

Refer this link for more information: http://ios-blog.co.uk/tutorials/quick-tips/how-to-create-rounded-avatars-in-your-ios-application/

Galasyn answered 2/5, 2014 at 5:18 Comment(0)
U
1

I had a similar issue, my UIImageView was initially a square and would only show as circular when the UITableViewCell it was within was either highlighted or selected.

It was a simple fix:

Swift 2.0

imgView.layer.cornerRadius = imgView.frame.width / 2
imgView.clipsToBounds = true

This was placed inside the awakeFromNib() for my custom UITableViewCell.

This is assuming imgView is the name of the UIImageView hooked up via storyboard inside this custom UITableViewCell.

Unhelm answered 29/1, 2016 at 3:57 Comment(0)
G
0

Set the image view to a circle inside the async call where you set the image.

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{

    NSString * imageString = [tweet valueForKeyPath:@"user.profile_image_url"];
    NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:imageString]];

    if (imageData != nil)
    {
        dispatch_async(dispatch_get_main_queue(), ^{

            cell.imageView.image = [UIImage imageWithData: imageData];
cell.imageView.layer.cornerRadius = cell.imageView.frame.size.width / 2.0;
cell.imageView.layer.borderWidth = 3.0;
cell.imageView.layer.borderColor = [UIColor colorWithRed:157.0/255.0 green:34.0/255.0 blue:53.0/255.0 alpha:1.0]
.CGColor;
cell.imageView.clipsToBounds = YES;
            [cell setNeedsLayout];
        });
    }
});
Glazing answered 7/4, 2016 at 15:10 Comment(0)
K
0
@interface MyCell : UITableViewCell
@end

@implementation MyCell

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.imageView.layer.masksToBounds = YES;
    self.textLabel.font = [UIFont systemFontOfSize:17];
    self.textLabel.textColor = [UIColor darkTextColor];
}

// --- image view frame is empty rect inside tableView: willDisplayCell:
// +++ set cornerRadius inside layoutSubviews works. 
- (void)layoutSubviews
{
    [super layoutSubviews];

    // layout image view
    CGRect vfr = self.frame;
    CGRect imgvr = self.imageView.frame;
    imgvr.origin.x = 16;
    imgvr.size.width = CGRectGetHeight(vfr);
    self.imageView.frame = imgvr;

    // update corner radius
    self.imageView.layer.cornerRadius = imgvr.size.width * 0.5f;

    // layout label
    CGRect lblr = self.textLabel.frame;
    lblr.origin.x = CGRectGetMaxX(imgvr) + 16;
    lblr.size.width = CGRectGetWidth(vfr) - CGRectGetMaxX(imgvr) - 32;
    self.textLabel.frame = lblr;
}

@end
Kentiga answered 14/7, 2016 at 12:14 Comment(0)
J
0

In case your cell is by code:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let myImageView = (cell as! MyCustomCell).myImageView
        myImageView.layoutIfNeeded()
        myImageView.layer.cornerRadius = myImageView.frame.width / 2.0
 }
Jessamyn answered 13/6, 2019 at 17:25 Comment(0)
W
0
cell.imageView?.layer.cornerRadius = 22.0
cell.imageView?.layer.masksToBounds = true
Wildeyed answered 11/10, 2019 at 22:58 Comment(1)
Please describe in your answer, what was the problem, and how will this snippet solve it, to help others understand this answerWeltschmerz
D
-1

Here is a perfect and state away solution for circular image in UITableview Cell. Simply modify your UITableviewCell (custom cell) class with below code.

override func awakeFromNib() {
    super.awakeFromNib()
    imgEvent.layer.frame = (imgEvent.layer.frame).insetBy(dx: 0, dy: 0)
    imgEvent.layer.borderColor = UIColor.gray.cgColor
    imgEvent.layer.cornerRadius = (imgEvent.frame.height)/2
    imgEvent.layer.masksToBounds = false
    imgEvent.clipsToBounds = true
    imgEvent.layer.borderWidth = 0.5
    imgEvent.contentMode = UIViewContentMode.scaleAspectFill
  }

It will also helps to solve the problem of image circular only after scrolling table..(if anyenter image description here)

Dyandyana answered 24/3, 2017 at 1:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.