bfeher / BFPaperTableViewCell

A subclass of UITableViewCell for iOS inspired by Google's Paper Material Design.
MIT License
368 stars 44 forks source link

Rounded corners on table cell #12

Closed artworkad closed 9 years ago

artworkad commented 9 years ago

I have subclassed BFPaperTableViewCell and applied rounded corners in drawRect:

UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSizeMake(2, 2)).fill()

The problem is that the ripple effect fills the entire cell and removes the rounded corners. Any idea how to solve this? @bfeher

bfeher commented 9 years ago

Hi ArtworkAD!

Thanks for submitting this issue :)

Right now, there is no support for rounded corners set in drawRect. I will try to release a new version soon with rounded corner support.

Sorry about that!

bfeher commented 9 years ago

Until then, the tap-circle layer and fade layer get their corner radius from self.layer.cornerRadius. If you can set that in your code, it should work. However I am noticing a very odd bug where even though the corner radius and frame are the same, the tap-circle layer does not fully cover the cell's frame: roundedcornerbug

I'll try and get this worked out soon.

bfeher commented 9 years ago

Update: It seems to work for most values and breaks for only a very few. For example, in the demo app with cells of height 64, after setting the self.layer.cornerRadius property in the subclass of BFPaperTableViewCell, it works for all values except the range [21, 31]. I really have no idea why its breaking for those values and only those values. I'll keep looking into it and try to implement a fix. Until then, please try setting the .layer.cornerRadius property in your code after setting the frame with drawRect.

bfeher commented 9 years ago

Another update for a possible quick-fix:

Sorry to spam you but I am trying to find a quick solution for you until I have the time to work out a better, permanent solution.

As long as your cells have either

self.clipsToBounds = YES;
// or
self.layer.masksToBounds = YES;

Then the only thing you have to do for a quick fix, is to delete or comment-out the line of code which sets the mask: (found in BFPaperTableViewCell.m) screen shot 2015-04-13 at 10 04 18 screen shot 2015-04-13 at 10 04 07

artworkad commented 9 years ago

@bfeher thank you for the fast reply. I am not familiar with corner radius but as I can remember from my research there is no way to set Top,Bottom,Left,Right corners independently. This is why I choose UIBezierPath. First I defined corner types:

enum CornerType {
    case Top
    case Bottom
    case None
    case All
}

Then in drawRect of my subclassed BFPaperTableViewCell I do:

if self.type == CornerType.Top {
    UIBezierPath(roundedRect: rect, byRoundingCorners: (UIRectCorner.TopLeft | UIRectCorner.TopRight), cornerRadii: CGSizeMake(2, 2)).fill()
} else if self.type == CornerType.Bottom {
    UIBezierPath(roundedRect: rect, byRoundingCorners: (UIRectCorner.BottomLeft | UIRectCorner.BottomRight), cornerRadii: CGSizeMake(2, 2)).fill()
} else if self.type == CornerType.All {
    UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSizeMake(2, 2)).fill()
} else {
    UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.allZeros, cornerRadii: CGSizeMake(2, 2)).fill()
}

Usually in a table view you just want the first and the last row have top/bottom corners. All rows in between have zero corners.

It would be great if you could add such feature while taking into account the ripple effect.

bfeher commented 9 years ago

Thanks for the info @ArtworkAD! I will try to add that feature. Until then, are you able to remove the line I mentioned above (tapCircle.mask = mask;) ?

If your cells clip their subviews then this might temporarily fix your issue. Any luck?

artworkad commented 9 years ago

@bfeher yes I tried but it did not work for me. It's not so much of an issue right now so I will wait for this feature.

bfeher commented 9 years ago

Hmm. Well right now all of the BFPaper components use their frame to set a mask for the animation layers. I think the easiest fix then is to add a property UIBezierPath maskPath which will act as the mask.

I will try and release this fix asap. Thanks again :)

bfeher commented 9 years ago

Hi @ArtworkAD!

I pushed a new version, 2.3.1 which added a new property, UIBezierPath *maskPath!

You can set that to any path you want and that will act as the new mask path for the ripples. If you leave it alone or set it to nil (default is nil), then the standard behavior will take effect and it will use the frame and self.layer.cornerRadius to try and make a mask just like before.

Give this a try and let me know if it works for you! Thanks again :D

artworkad commented 9 years ago

@bfeher where do I set the path? The problem is that we have to pass the roundedRect parameter from the draw function.

bfeher commented 9 years ago

In your subclass' drawRect can you access self.maskPath ?

artworkad commented 9 years ago

@bfeher Yes, now I have

override func drawRect(rect: CGRect) {

    super.drawRect(rect)

    // Set white background

    UIColor.whiteColor().setFill()

    // Apply rounded corners depending on cell position

    if self.type == CornerType.Top {
        self.maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: (UIRectCorner.TopLeft | UIRectCorner.TopRight), cornerRadii: CGSizeMake(2, 2))
    } else if self.type == CornerType.Bottom {
        self.maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: (UIRectCorner.BottomLeft | UIRectCorner.BottomRight), cornerRadii: CGSizeMake(2, 2))
    } else if self.type == CornerType.All {
        self.maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.AllCorners, cornerRadii: CGSizeMake(2, 2))
    } else {
        self.maskPath = UIBezierPath(roundedRect: rect, byRoundingCorners: UIRectCorner.allZeros, cornerRadii: CGSizeMake(2, 2))
    }

    self.maskPath.fill()
}

But the rounded corners still disappear on tap.

bfeher commented 9 years ago

oh! Can you confirm for me: Is the ripples path ok but the backgroundFade is still showing corners? I didn't make a maskPath for the background fade! DOH

artworkad commented 9 years ago

@bfeher just checked it. The backgroundFadeproperty is creating corners, while tapCircle is correctly showing rounded corners.

bfeher commented 9 years ago

thanks! I'm fixing it now, sorry!

bfeher commented 9 years ago

Pushed version 2.3.2 which should now fix this problem. Please let me know if there is anything else! Thanks :D

artworkad commented 9 years ago

@bfeher thank you :) it works great. Look at this beauty :dancer:

datei 16 04 15 08 36 37

bfeher commented 9 years ago

Awesome! That table looks amazing by the way. Actually is there any way that you could share with me how you got your table to look like that? XD

artworkad commented 9 years ago

:D @bfeher I am going to share it soon. Just have to finish some stuff. Stay tuned.

bfeher commented 9 years ago

Great thanks!