UIImageView circular shape swift - ios

I used this code to make UIImageView in a custom UITableViewCell, but the circular shape isn't updated until i pressed on the table cell, I tried the code in both awakeFromNib() and layoutSubviews()
userImage.layer.cornerRadius = userImage.frame.size.width / 2
userImage.layer.masksToBounds = true
userImage.layer.borderColor = UIColor.black.cgColor
userImage.layer.borderWidth = 1

You simply have to override the layoutSubviews() method of your UITableViewCell subclass, as it will be called on drawing updates.
Then just set your UIImageView's cornerRadius as you like:
class MyCustomTableViewCell: UITableViewCell {
private let circularImageView: UIImageView = {
$0.contentMode = .scaleAspectFill
$0.layer.masksToBounds = true
$0.layer.borderColor = UIColor.black.cgColor
$0.layer.borderWidth = 1
return $0
}(UIImageView())
// ...
override func layoutSubviews() {
super.layoutSubviews()
circularImageView.layer.cornerRadius = circularImageView.frame.size.width/2
}
}

if you create you tableviewCell programmatically you have to override init
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//put your code here
}

update the imageViews cornerRadius just after a little time. Because frame.size.width / 2 will be different at runtime :
DispatchQueue.main.asyncAfter(deadline : .now() + 0.05 {
self.userImage.layer.cornerRadius = userImage.frame.size.width / 2
self.userImage.layer.masksToBounds = true
self.userImage.layer.borderColor = UIColor.black.cgColor
self.userImage.layer.borderWidth = 1
}

Related

Can't change border colour of switch inside tableview's cell

I've a switch inside table which I'm creating programmatically. I can't change switch's off border colour to gray. I tried tint colour which isn't working either.
How to fix it?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as? TableViewCell else {
fatalError("...")
}
//...
let switchView = UISwitch()
switchView.layer.borderColor = UIColor.greyColour.cgColor
cell.accessoryView = switchView
return cell
}
You didn't specify what effect you want to achieve but for layer.borderColor to work you need to setup layer.borderWidth also. However, because switch layer is rectangular it will look like this:
Which might be not what you want. So to make the border follow the switcher's shape you'll need to modify its corner radius:
switchView.layer.borderColor = UIColor.gray.cgColor
switchView.layer.borderWidth = 1.0
switchView.layer.cornerRadius = 16.0
to make it looks like this:
Update
If you want to apply border only for switcher off state it'll be a bit more tricky because you need to handle switcher states changes. The easiest way I could think of is to subclass UISwitch and provide your own behaviour by overriding sendActions method:
class BorderedSwitch: UISwitch {
var borderColor: UIColor = UIColor.gray {
didSet {
layer.borderColor = borderColor.cgColor
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
override var isOn: Bool {
didSet {
updateState()
}
}
override func sendActions(for controlEvents: UIControl.Event) {
super.sendActions(for: controlEvents)
if controlEvents.contains(.valueChanged) {
updateState()
}
}
private func setup() {
layer.borderColor = borderColor.cgColor
layer.cornerRadius = frame.height / 2
layer.borderWidth = 1.0
}
private func updateState() {
layer.borderWidth = isOn ? 0.0 : 1.0
}
}
Notice that I also updated cornerRadius value to frame.height / 2 to avoid magic numbers
If you add a switch with code, it looks just like a switch you add in a storyboard. Neither way of creating a switch has a border color.
The code below adds a switch to a view controller's content view:
#IBOutlet var switchView: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
switchView = UISwitch()
switchView.translatesAutoresizingMaskIntoConstraints = false //Remember to do this for UIViews you create in code
if false {
//Add a gray border to the switch
switchView.layer.borderWidth = 1.0 // Draw a rounded rect around the switchView so you can see it
switchView.layer.borderColor = UIColor.gray.cgColor
switchView.layer.cornerRadius = 16
}
//Add it to the container view
view.addSubview(switchView)
//Create center x & y layout anchors (with no offset to start)
let switchViewXAnchor = switchView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0)
switchViewXAnchor.isActive = true
let switchViewYAnchor = switchView.centerYAnchor.constraint(equalTo: view.centerYAnchor,
constant: 0.0)
switchViewYAnchor.isActive = true
}
It looks perfectly normal.

UIButton corner radius not working properly in CustomClass

I've make a custom class for UIButton but in small screen devices e.g. iPhone 5s cornerRadius not working properly
You've to looks closer to see the UiButton's cornerRadius is not perfectly rounded
class customRoundButton: UIButton
{
override func awakeFromNib()
{
self.layer.cornerRadius = (self.layer.frame.height / 2)
self.layer.borderColor = fontColor.defualtBlue.cgColor
self.layer.borderWidth = 1
self.layer.clipsToBounds = true
self.layer.layoutIfNeeded()
}
}
Setting the cornerRadius in awakeFromNib is too early. Use layoutSubviews instead:
class CustomRoundButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
layer.borderColor = UIColor.blue.cgColor
layer.borderWidth = 1
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = layer.frame.height / 2
}
}
Try
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.height * 0.50
}
So by the time your custom UIButton is going to be added to the subviews it will know it bounds and you just have to assign the corner radius to be the half of bounds height.
Better use IBDesignable for this :
#IBDesignable
class RoundedButton: UIButton {
#IBInspectable var cornerRadius: CGFloat = 3.0 {
didSet {
self.layer.cornerRadius = cornerRadius
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.setupView()
}
override func awakeFromNib() {
super.awakeFromNib()
self.setupView()
}
func setupView() {
self.layer.masksToBounds = false
self.layer.cornerRadius = cornerRadius
}
}
I stumbled upon this question here and found for me what worked best in Swift 5 is setting the corner radius in awakeFromNib inside Disptatch.main.async When using layoutSubviews or setNeedsLayout the closure is called for every little change or movement. This might work for some use cases. I have not tried that with the above example.
My code looks like this:
override func awakeFromNib() {
super.awakeFromNib()
imageView.layer.masksToBounds = false
imageView.clipsToBounds = true
DispatchQueue.main.async {
self.imageView.layer.cornerRadius = self.imageView.bounds.height / 2.0
}
}

Draw a cell of UITableView give a visual error

I write a code to draw card in a UITableView, each card need to draw itself and have a custom rowheight in the exemple a draw 2 card in 240 height and 8 other with 240/2 of height.
I give you a screen of the problem :
The last but one card have a strange design. When I print the bounds of the frame of it, this show me the same size that the other ...
I give you my code where I draw the card :
func drawBasiqCard() -> CGFloat{
if(cardView.subviews.count == 0){
self.addSubview(cardView)
cardView.frame = CGRect(marginCardWidth,
marginCardHeight,
self.bounds.size.width - (marginCardWidth*2),
basiqCardtHeight - (marginCardHeight*2))
cardView.layer.cornerRadius = 10
print(cardView.bounds.size.height)
}
if(self.ShadowLayerCard == nil){
let rounding = CGFloat.init(10)
let shadowLayer = CAShapeLayer.init()
self.ShadowLayerCard = shadowLayer
shadowLayer.path = UIBezierPath.init(roundedRect: cardView.bounds, cornerRadius: rounding).cgPath
shadowLayer.fillColor = UIColor(rgb: 0xffcc00).cgColor
shadowLayer.shadowPath = shadowLayer.path
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowRadius = 5
shadowLayer.shadowOpacity = 0.2
shadowLayer.shadowOffset = CGSize.init(width: 0, height: 0)
cardView.layer.insertSublayer(shadowLayer, at: 0)
}
return cardView.bounds.size.height + (marginCardHeight*2)
}
So my question is, the code above is good ? Or my error are not here ? Where is the code can be produce this visual error ?
If you need the code of the UITableView I can show you.
Thank for your reply.
This could happen if you set the shadow of the view before it's bounds has been set.
Your current design is not good, you should add a shadow to the contentView in init and then change the contentView's frame(add some padding) in layoutsubviews.
Here is an example:
import UIKit
class TableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.do {
$0.backgroundColor = .white
$0.addShadow(ofColor: .black, radius: 1.5, offset: .zero, opacity: 0.1)
$0.cornerRadius = 6
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
contentView.pin.all(UIEdgeInsets(inset: 5))
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
contentView.backgroundColor = highlighted ? UIColor(rgb: 217) : .white
}
}
It looks like:

Accessory Type in UITableViewCell subclass is not visible

I'm doing everything programmatically. I have a UITableView with its rows being a UITableViewCell subclass. I have been unable to set the accessoryType of my cell as nothing appears on the screen. Later on I want to be able to select a cell, and add a checkmark when selected.
class ContactsTableViewCell: UITableViewCell {
let name = UILabel()
let phoneNumber = UILabel()
let iPADFACTOR:CGFloat = DeviceHelper().isIPAD ? 1.4: 1.0
var rowSelected = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
phoneNumber.font = UIFont.systemFontOfSize(15)
phoneNumber.textColor = UIColor.lightGrayColor()
self.contentView.addSubview(name)
self.contentView.addSubview(phoneNumber)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
let margeV:CGFloat = 5.0*iPADFACTOR
let margeH = self.frame.width*0.05
name.frame = CGRectMake(margeH, margeV, self.frame.width - margeH * 4, 18)
phoneNumber.frame = CGRectMake(margeH, name.frame.maxY + 5, self.frame.width - margeH * 4, 15)
}
}
As you can see I'm using the layoutSubviews() method, to set the frame of my labels and I've tried playing with the label size to check if somehow it was hiding the accessoryView without success. I've even tried setting their frame to 0.
I'm also not sure if I'm setting my frames correctly. Should I use self.contentView.frame instead of self.frame ?
Any help is appreciated, thanks.
override func layoutSubviews() {
super.layoutSubviews()
let margeV:CGFloat = 5.0*iPADFACTOR
let margeH = self.frame.width*0.05
name.frame = CGRectMake(margeH, margeV, self.frame.width - margeH * 4, 18)
phoneNumber.frame = CGRectMake(margeH, name.frame.maxY + 5, self.frame.width - margeH * 4, 15)
}
if (YES) {
cell.accessoryType = UITableViewCellAccessoryType.Checkmark
} else {
cell.accessoryType = UITableViewCellAccessoryType.None;
}

Custom Table View Cell Drawing Wrong Height When Scrolling

I'm customizing my table view cell inside the willDisplayCell method. For some reason it is drawing some subviews with the wrong height while scrolling (see video). I can't figure out why...
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.contentView.backgroundColor=UIColor.clearColor()
cell.reloadInputViews()
let height = cell.frame.height - 15
var whiteRoundedCornerView:UIView!
whiteRoundedCornerView=UIView(frame: CGRectMake(7,10,self.view.bounds.width-14,height))
whiteRoundedCornerView.backgroundColor=getColorByID(colorID!)
whiteRoundedCornerView.layer.masksToBounds=false
whiteRoundedCornerView.layer.shadowOpacity = 1.55;
whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(1, 0);
whiteRoundedCornerView.layer.shadowColor=UIColor.grayColor().CGColor
whiteRoundedCornerView.layer.cornerRadius=5.0
whiteRoundedCornerView.layer.shadowOffset=CGSizeMake(-1, -1)
whiteRoundedCornerView.layer.shadowOpacity=0.5
whiteRoundedCornerView.layer.shouldRasterize = true
whiteRoundedCornerView.layer.rasterizationScale = UIScreen.mainScreen().scale
if cell.contentView.subviews.count < 6 { // to avoid multible subview adding when scrolling...
cell.contentView.addSubview(whiteRoundedCornerView)
cell.contentView.sendSubviewToBack(whiteRoundedCornerView)
}
}
Here is a video of the issue:
https://vid.me/QeV0
Update:
I also tried to move the code to layoutSubviews but still the same issue...
override func layoutSubviews() {
super.layoutSubviews()
let height = self.frame.height - 15
var whiteRoundedCornerView:UIView!
whiteRoundedCornerView=UIView(frame: CGRectMake(7,10,UIScreen.mainScreen().bounds.width-14,height))
whiteRoundedCornerView.backgroundColor=UIColor.greenColor()//getColorByID(colorID!)
whiteRoundedCornerView.layer.masksToBounds=false
whiteRoundedCornerView.layer.shadowOpacity = 1.55;
whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(1, 0);
whiteRoundedCornerView.layer.shadowColor=UIColor.grayColor().CGColor
whiteRoundedCornerView.layer.cornerRadius=5.0
whiteRoundedCornerView.layer.shadowOffset=CGSizeMake(-1, -1)
whiteRoundedCornerView.layer.shadowOpacity=0.5
whiteRoundedCornerView.layer.shouldRasterize = true
whiteRoundedCornerView.layer.rasterizationScale = UIScreen.mainScreen().scale
if self.contentView.subviews.count < 6 {
self.contentView.addSubview(whiteRoundedCornerView)
self.contentView.sendSubviewToBack(whiteRoundedCornerView)
}
}
If i don't check the tableview.subviews.count it will add tons of subviews to the cell while scrolling.
I want to change the height of the existing subview when the cell is reused.
You have a check to not add the subviews multiple times. When that case happens you already have added the subviews earlier but their height may now be wrong and you must update them.
UITableView reuses cells so a new cell with different height might already contain your subviews but with the wrong height since you don't update it.
You should cleanly separate the set-up of your subview and the layout like so:
class MyCell: UITableViewCell {
private let whiteRoundedCornerView = UIView()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUp()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUp()
}
override func layoutSubviews() {
super.layoutSubviews()
let bounds = self.bounds
var whiteRoundedCornerViewFrame = CGRect()
whiteRoundedCornerViewFrame.origin.x = 7
whiteRoundedCornerViewFrame.origin.y = 10
whiteRoundedCornerViewFrame.size.width = bounds.width - 7 - whiteRoundedCornerViewFrame.origin.x
whiteRoundedCornerViewFrame.size.height = bounds.height - 5 - whiteRoundedCornerViewFrame.origin.y
whiteRoundedCornerView.frame = whiteRoundedCornerViewFrame
}
private func setUp() {
setUpWhiteRoundedCornerView()
}
private func setUpWhiteRoundedCornerView() {
let child = whiteRoundedCornerView
child.backgroundColor = .greenColor()
let layer = child.layer
layer.cornerRadius = 5.0
layer.rasterizationScale = UIScreen.mainScreen().scale
layer.shadowColor = UIColor.grayColor().CGColor
layer.shadowOffset = CGSize(width: -1, height: -1)
layer.shadowOpacity = 0.5
layer.shouldRasterize = true
insertSubview(child, atIndex: 0)
}
}
If the data on different rows is of different size then you have to set the height of the tableview cell dynamically
Here is the code:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{
var height:CGFloat
let constraint1:CGSize = CGSizeMake(self.view.frame.size.width/2-70, 5000.0)
let string="eefdgvfgfhgfgfhgfgjhidffjo;dkfnkjfldjfkjfkjfldfjkkjhbkjflfjihkfjkfjgfkjfkgfkgjlfgnfjgnfgnfgbkgmfjgfkgjfkggjlfgklkgkgkglkgggfkglgkkgjlgkgk"
let answerSize = string.boundingRectWithSize(constraint1, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(17.0)], context: nil)
let questionSize = string.boundingRectWithSize(constraint1, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: UIFont.systemFontOfSize(17.0)], context: nil)
height=answerSize.height + questionSize.height
return height
}

Resources