label frame not stay Properly in `UICollectionViewCell` - ios

I am developing custom calendar by UICollectionView.
I want to show circle backGround of label for today's date.
my code inside uitableviewCell:
let todayDate = Date().removeTimeStamp()
self.lblDate.text = "\(String(describing: day))"
if date == todayDate{
lblDate.textColor = .white
lblDate.layer.cornerRadius = lblDate.frame.width/2
lblDate.layer.backgroundColor = UIColor.appOrange.cgColor
}else if date < todayDate {
lblDate.textColor = .lightGray
lblDate.layer.backgroundColor = UIColor.white.cgColor
}else{
lblDate.textColor = .black
lblDate.layer.backgroundColor = UIColor.white.cgColor
}
but i am not getting proper circle.see:
and the shape of circle get changed when i change the size of UICollectionViewCell from StoryBoard.
the lable having 1:1 aspect ration constraint.
What can i do for proper circle??
Thanks!!

set it inside
func layoutSubviews()
{
super.layoutSubviews()
lblDate.layer.cornerRadius = lblDate.frame.width/2
lblDate.clipsToBounds = true
}

The problem is, When we accessing labels frame before it properly finish layouting, we got wrong Frame.
Solution:
You could override layoutSubviews method of your UICollectionView class.
func layoutSubviews() {
super.layoutSubviews()
lblDate.layer.cornerRadius = lblDate.frame.width/2
}

Also you can create global func:
extension UILabel {
func setRoundEdge() {
let radius = self.frame.height/2
self.layer.borderWidth = 0.3
self.layer.masksToBounds = false
self.layer.borderColor = UIColor.black.cgColor
self.layer.cornerRadius = radius
self.layer.masksToBounds = true
}
}

Related

Drop shadow in UICollectionViewCell not accurate

I am not able to get accurate shadow for collectionview cell which has a UIImage and a label.
I have collection view for which shadow appears properly. Below are code snippets for both and screenshot showing cell with problem and yellow collection view with proper shadow. I went through many posts but unable to get solution that can get shadow similar to collection view.
For Collection view that is embedded in UIView and proper shadow
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
enclosureView.layer.shadowPath = UIBezierPath(rect: enclosureView.bounds).cgPath
}
override func viewDidLoad() {
super.viewDidLoad()
enclosureView.layer.shadowColor = UIColor.systemGray2.cgColor
enclosureView.layer.shadowOpacity = 1
enclosureView.layer.shadowOffset = .zero
enclosureView.layer.shadowRadius = 5
enclosureView.layer.masksToBounds = false
enclosureView.cornerRadius = 10
}
For Collection view cell having UIImage and UILabel.
UIImage is embedded in UIView. I want shadow around image and not around cell.
class cell: UICollectionViewCell {
override func awakeFromNib() {
super.awakeFromNib()
self.layer.masksToBounds = false
self.clipsToBounds = false
image.layer.cornerRadius = 10
image.clipsToBounds = true
image.backgroundColor = .clear
imageEnclosureView.layer.masksToBounds = false
imageEnclosureView.clipsToBounds = false
imageEnclosureView.layer.shadowRadius = 5
imageEnclosureView.layer.shadowOpacity = 1
imageEnclosureView.layer.shadowColor = UIColor.systemGray2.cgColor
imageEnclosureView.layer.shadowOffset = .zero
imageEnclosureView.backgroundColor = .clear
}
override func layoutSubviews() {
super.layoutSubviews()
self.imageEnclosureView.layer.shadowPath = UIBezierPath(
roundedRect: imageEnclosureView.bounds,
cornerRadius: 10
).cgPath
}
}

UIView not shows round

For making a circular UIView I am using the cornerRadius property.
I have a UIView with dimension 79*158.
redView.layer.cornerRadius = redView.frame.size.height/2
redView.layer.masksToBounds = true
It shows elipse instead of circle:
Any workaround or does it only work with square type (eg. UIView(100*100))?
I am ok if it resizes dynamically.
use this...
func makeCircle (view: UIView) {
view.clipsToBounds = true
let height = view.frame.size.height
let width = view.frame.size.width
let newHeight = min(height, width) // use "max" if you want big circle
var rectFrame = view.frame
rectFrame.size.height = newHeight
rectFrame.size.width = newHeight
view.frame = rectFrame
view.layer.cornerRadius = newHeight/2
}
use like this:
#IBOutlet var rectView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
makeCircle(view: rectView)
}
You have a UIView with dimension 79*158.So that is wrong. You should have exactly same height and width for rounding exact a view to circle shape.
E.g.
redView.frame.size.height = 79.0
redView.frame.size.width = 79.0
or
redView.frame.size.height = 158.0
redView.frame.size.width = 158.0
And apply corner radius like:
redView.clipsToBounds = true
redView.layer.cornerRadius = redView.frame.size.height / 2.0
Result:
Note: Check your constrains also If you are using Auto Layout. Be sure view frame doesn't change.
If you are using constraints then changing the frame/bounds of the view is not a good idea. Instead you should do the following.
If the view is contained in a UIViewController then set the cornerRadius in viewDidLayoutSubviews method
And if the view is itself a subclass of UIView the set the cornerRadius in layoutSubviews method
Only Squire view make a perfect circle. For example, if your view size is (10*10),(50*50),(100*100), etc. then your view becomes perfect squire else not.
Using IBDesignable, you can display without project run in storyboard ox .XIB #simple way
Step 1. Subclass UIView:
#IBDesignable class RoundedCornerView: UIView {
#IBInspectable var borderWidth:CGFloat = 2 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor:UIColor = UIColor.orangeGradientLight {
didSet {
layer.borderColor = borderColor.cgColor
}
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = frame.height/2
layer.masksToBounds = true
layer.borderColor = borderColor.cgColor
layer.borderWidth = borderWidth
}
}
Step 2. Set custom class in identity inspector:
can't.
Try resize UIView to square: 79*79 OR 158*158
And set:
redView.layer.cornerRadius = redView.frame.size.height/2

Circular ImageView Swift

I have tried every answer variation I have found and all give me the same result. A weird almost diamond shaped image view. I was using this:
imageView.layer.cornerRadius = imageView.frame.width/2
imageView.clipsToBounds = true
This worked with a previous project I was working on but now when I try it I get the weird diamond.
Here is the solution how to create UIImageView Circular. This Approach is new
Create a new Designable.swift file in your project.
Copy the following code in your Designable.swift file.
import UIKit
#IBDesignable class DesignableImageView: UIImageView { }
#IBDesignable class DesignableButton:UIButton { }
#IBDesignable class DesignableTextField:UITextField { }
extension UIView {
#IBInspectable
var borderWidth :CGFloat {
get {
return layer.borderWidth
}
set(newBorderWidth){
layer.borderWidth = newBorderWidth
}
}
#IBInspectable
var borderColor: UIColor? {
get{
return layer.borderColor != nil ? UIColor(CGColor: layer.borderColor!) :nil
}
set {
layer.borderColor = newValue?.CGColor
}
}
#IBInspectable
var cornerRadius :CGFloat {
get {
return layer.cornerRadius
}
set{
layer.cornerRadius = newValue
layer.masksToBounds = newValue != 0
}
}
#IBInspectable
var makeCircular:Bool? {
get{
return nil
}
set {
if let makeCircular = newValue where makeCircular {
cornerRadius = min(bounds.width, bounds.height) / 2.0
}
}
}
}
Now after this select your ImageView on StoryBoard and Select Identity Inspector from Utilities Panel.
In Custom Class section select the custom class from the drop-down menu naming DesignableImageView and hit return. You will see the designable update after hitting return.
Now go to attribute inspector in utility panel and you can add the desired Corner Radius for the image to be circular.
P.S. If your image is rectangle this will try to make it square and then best possible circle.
Attached images for reference.
Try changing the view mode for the uiimageview. It might have been set to Aspect fit making it to look like a diamond.
Or you can create a circular uiimage using the code below,
imageLayer.contents = yourImage.CGImage
let mask = CAShapeLayer()
let dx = lineWidth + 1.0
let path = UIBezierPath(ovalInRect: CGRectInset(self.bounds, dx, dx))
mask.fillColor = UIColor.blackColor().CGColor
mask.path = path.CGPath
mask.frame = self.bounds
layer.addSublayer(mask)
imageLayer = CAShapeLayer()
imageLayer.frame = self.bounds
imageLayer.mask = mask
imageLayer.contentsGravity = kCAGravityResizeAspectFill
layer.addSublayer(imageLayer)
If you want to create with new image it may be like this
let img = UIImage(named: "logo.png")
UIGraphicsBeginImageContextWithOptions(imgView.bounds.size, false, 0.0);
// Add a clip before drawing anything, in the shape of an rounded rect
UIBezierPath(roundedRect: imgView.bounds, cornerRadius:imgView.bounds.size.width/2).addClip()
img!.drawInRect(imgView.bounds)
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
Ref & If you want to make extension for it : https://stackoverflow.com/a/25459500/4557505
You can find more information in the above link for other alternative solutions
Your image view should be a square in order for this to work.
if you are trying this code in viewDidLoad(), please try it in viewDidLayoutSubviews()
viewDidLayoutSubviews() {
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.layer.masksToBounds = true
}
extension UIImageView {
public func maskCircle(inputImage: UIImage) {
self.contentMode = UIViewContentMode.scaleAspectFill
self.layer.cornerRadius = self.frame.height / 2
self.layer.masksToBounds = false
self.clipsToBounds = true
self.image = inputImage
}
}
Usage example of the above extension:
let yourImage:UIImage = UIImage(named: "avatar")!
yourImageView.maskCircle(yourImage)

Add border to all labels in a view

In my app I have a custom view containerView in this view there are more than 20 labels and I want to apply a border style to all of them.
Is there a way to avoid to add the border to each of them avoiding to have a long list?
Something similar to:
for each label in containerView {
labels.layer.borderColor = UIColor.greenColor.CGColor
}
create a subclass like this:
#IBDesignable
class BorderedLabel: UILabel {
#IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
}
then change your label's custom class in interface builder, set the borderColor / borderWidth properties you like and see the results live in interface builder!
You need to set borderWidth.
for subview in self.view.containerView.subviews as! [UIView] {
if let label = subview as? UILabel {
label.layer.borderColor = UIColor.greenColor().CGColor
label.layer.borderWidth = 1
}
}
Swift 4
label.layer.borderColor = UIColor.green.cgColor
You can use this:
for view in self.view.containerView.subviews as! [UIView] {
if let label = view as? UITextField {
label.layer.borderColor = UIColor.blueColor().CGColor;
label.layer.borderWidth = 1;
}
}
}
My solution is:
for imageViews in self.containerView.subviews as! [UIImageView] {
imageViews.layer.borderColor = UIColor.greenColor().CGColor
imageViews.layer.borderWidth = 1
}

Subview in cell loses color when tableview is changing

I have an UITableView which has a dynamic subview.
When the table is static it looks like this:
The round view with the T is the custom subview
But when I choose edit and drag the table cell the it looses it's color and the T.
Whats the reason for this?
I initialize the cell like this (It's an prototype IB Cell):
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as Item
//cell.textLabel.text = object.valueForKey("name")!.description
let cSubView = cell.viewWithTag(100) as RoundedIcon
cSubView.setUpViewWithFirstLetter(String(first(object.name)!).uppercaseString)
}
And the RoundedIcon works like this:
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = self.frame.size.width / 2;
self.layer.borderWidth = 1.0;
self.layer.borderColor = UIColor.lightGrayColor().CGColor;
self.clipsToBounds = true;
}
func setUpViewWithFirstLetter(letter:String){
self.backgroundColor = RoundedIcon.UIColorFromRGB(0x68C3A3)
let theLetterLabel = UILabel()
theLetterLabel.text = letter
theLetterLabel.textColor = UIColor.whiteColor()
theLetterLabel.textAlignment = .Center
theLetterLabel.font = UIFont.systemFontOfSize(25)
self.addSubview(theLetterLabel)
theLetterLabel.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: self.frame.size)
}
#rdelmar's comment pointed me in the right direction that an UITableview changes the background color of all it's cells to:
UIColor(white:0,alpha:0)
If you don't want your view to change it's color you should change the backgroundColor property setter, which works in swift like this:
//override this setter to avoid color resetting on drag
override var backgroundColor:UIColor?{
didSet {
//check the color after setting - you also can do it earlier
if let bgCol = backgroundColor{
println(bgCol)
if bgCol == UIColor(white: 0, alpha: 0){ //check if it's settled by the table
super.backgroundColor = yourColor //set it back to your color
}
}
}
}

Resources