Changing the UIImage position programmarically - swift

I have a UITableView with sections. I added a UImage in each cell, but it is on the left side, how can I change it to make it go to the right side?
this is my code for each cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cells")
cell?.textLabel?.text = data[indexPath.section].subType[indexPath.row]
cell?.textLabel?.textAlignment = .right
cell?.textLabel?.font = UIFont(name: "GESSTwoLight-Light", size: 15)
cell!.isUserInteractionEnabled = false;
cell!.imageView?.image = UIImage(named: "username.png")
return cell!
}
This is my UITableView

you simply have to do the following in the tableView(_:cellForRowAt:) method:
cell.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
cell.textLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
cell.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
This will create the following
Credits goes to liau-jian-jie for sharing this solution, which also can be applied to UIButtons.

Related

Cached shadow path for UITableView

I want to cache a shadow path to make the performance of UITableView better.
I've read https://yalantis.com/blog/mastering-uikit-performance/ that
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
would stop offscreen shadows, however using the following function
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Cell data: \(data[indexPath.row])"
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
cell.imageView?.layer.shadowRadius = 8
cell.imageView?.layer.shadowOffset = CGSize(width: 3, height: 3)
cell.imageView?.layer.shadowOpacity = 0.5
cell.imageView?.layer.cornerRadius = 20
cell.imageView?.image = UIImage(named: "PlaceholderImage")
return cell
}
produces a result where some cells have the shadow and some don't.
How can I implement caching of shadow paths to all cells in a simple UITableView
The problem is these lines:
if let rect = cell.imageView?.bounds {
cell.imageView?.layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
If the cell's imageView has never been assigned an image, its frame is .zero and so its bounds is .zero. So the shadowPath ends up with a cgPath that is just a point, and no shadow appears.
The way I would solve this is that I would not use the built-in imageView property at all. I'd use a custom cell class with my own image view whose frame I can control, instead of the built-in imageView which plays these sorts of tricks.
if let shadowPath = self.shadowPathCache {
cell.imageView?.layer.shadowPath = shadowPath
} else if let rect = cell.imageView?.bounds {
self.shadowPathCache = UIBezierPath(rect: rect).cgPath
cell.imageView?.layer.shadowPath = self.shadowPathCache
}

TableView Cell view shadow does not coming properly in Swift

I have added view as a background for tableview cell and I am giving shadow for view. Here when I run tableview shadow does not coming properly, once I scroll down and up then shadow coming properly.
I have given shadow according to this answer answer
Code:
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowOffset = CGSize(width: -1, height: 1)
layer.shadowRadius = 1
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PlansTableViewCell
cell.containerView.dropShadow()
return cell
}
Before scrolling shadow coming like this:
after scrolling coming like below:
After running(before scrolling) also i need second image kind of output, Here Help me with the code.
Problem is here
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
bounds isn't correct at that time , try
call it from
override func layoutSubviews() {
super.layoutSubviews()
self.containerViewdropShadow()
}
or
cell.layoutIfNeeded()
cell.containerView.dropShadow()

I cannot able to add subview to UItableviewcell

Code
import UIKit
class ViewController:
UIViewController,UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var suma=UITableViewCell()
var sampleviewpurple=UIView(frame: CGRect(x: suma.frame.width/0, y: 0, width: suma.frame.width/2, height: suma.frame.height))
sampleviewpurple.backgroundColor=#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)
var sampleviewred=UIView(frame: CGRect(x: suma.frame.width/1, y: 0, width: suma.frame.width/2, height: suma.frame.height))
sampleviewred.backgroundColor=#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
suma.contentView.addSubview(sampleviewpurple)
suma.contentView.addSubview(sampleviewred)
return suma
}
#IBOutlet weak var tab: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tab.dataSource=self
tab.delegate=self
}
}
when I try to add a subview to the suma and return to the delegate, My table view is still blank, I am returning valid data source to the data source when and also noticed the reference to the table view all is fine, But still how I can not able to add a subview to the uitableviewcell
In the cellForRowAt function, you must dequeue your table cell, not instantiate UITableViewCell:
var suma = tableView.dequeueReusableCell(withIdentifier: "YOUR_CELL_IDENTIFIER")
For setting your view's frame you are using the cell's frame which is not set yet. You should use such a view which frame is already set and on which bases you want to calculate the frame of your new views.
Try this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var sumaCell:UITableViewCell?
sumaCell = tableView.dequeueReusableCell(withIdentifier: "sumaCell")
if sumaCell == nil {
sumaCell = UITableViewCell(style: .default, reuseIdentifier: "sumaCell")
}
var sampleviewpurple=UIView(frame: CGRect(x: 0, y: 0, width: ((sumaCell?.frame.width)!/2), height: (sumaCell?.frame.height)!))
sampleviewpurple.backgroundColor=#colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)
var sampleviewred=UIView(frame: CGRect(x: (sumaCell?.frame.width)!/2, y: 0, width: ((sumaCell?.frame.width)!/2), height: (sumaCell?.frame.height)!))
sampleviewred.backgroundColor=#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
sumaCell?.contentView.addSubview(sampleviewpurple)
sumaCell?.contentView.addSubview(sampleviewred)
return sumaCell!
}
You are creating the cell in code. First of all, you have to register the UITableViewCell in viewDidLoad method.
tab.register(UITableViewCell.self, forCellReuseIdentifier: "DefaultCell")
Then you have to use the dequeue cell in cellForRowAt method.
var suma = tab.dequeueReusableCell(withIdentifier: "DefaultCell")
If you are instantiating the cell from storyboard, you just have to use dequeue cell. No need to register.
I made three change.
Dequeue the cell for reusability.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var suma = UITableViewCell()
suma = tab.dequeueReusableCell(withIdentifier: "DefaultCell")!`
Changed the sampleviewpurple and sampleviewred x position
let sampleviewpurple = UIView(frame: CGRect(x: 0, y: 0, width: suma.frame.width/2, height: suma.frame.height))
let sampleviewred = UIView(frame: CGRect(x: suma.frame.width/2, y: 0, width: suma.frame.width/2, height: suma.frame.height))
Registered the cell which is created programmatically to create a connection between UITableView and UITableViewCell in viewDidLoad function
tab.register(UITableViewCell.self, forCellReuseIdentifier: "DefaultCell")

Adding shadow to tableview cell cause laggy scroll and duplicate shadow

I have added white space around my tableview cell and every time I scroll this shadows getting bigger and bigger when I scroll, and its get lag when I scroll for the second and third time with the bigger shadow
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.backgroundColor = UIColor.clear
cell.contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x:10,y: 5,width: self.view.frame.size.width - 20,height: 117))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
//whiteRoundedView.layer.masksToBounds = true
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1,height: 1)
whiteRoundedView.layer.shadowOpacity = 0.2
let shadowPath = UIBezierPath(rect: whiteRoundedView.layer.bounds)
whiteRoundedView.layer.shouldRasterize = true
whiteRoundedView.layer.shadowPath = shadowPath.cgPath
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
return cell
}
Just put code inside the awakefrom nib
class CustomCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.backgroundColor = UIColor.clear
self.contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x:10,y: 5,width: self.contentView.frame.size.width - 20,height: 117))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
//whiteRoundedView.layer.masksToBounds = true
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1,height: 1)
whiteRoundedView.layer.shadowOpacity = 0.2
let shadowPath = UIBezierPath(rect: whiteRoundedView.layer.bounds)
whiteRoundedView.layer.shouldRasterize = true
whiteRoundedView.layer.shadowPath = shadowPath.cgPath
self.contentView.addSubview(whiteRoundedView)
self.contentView.sendSubview(toBack: whiteRoundedView)
}
}
You keep adding shadow views on top of each other without ever removing them. If all your cells will need the shadow you can just add a tag and check if a view with that tag already exists like so:
whiteRoundedView.tag = 12345
if cell.contentView.viewWithTag(12345) == nil {
cell.contentView.addSubview(whiteRoundedView)
}
If some cells have the shadow but some cells don't you could do it like this:
if let shadowView = cell.contentView.viewWithTag(12345) && noShadow {
shadowView.removeFromSuperview
} else if !noShadow {
cell.contentView.addSubview(whiteRoundedView)
}
Alternatively like mentioned in the comments of the question you would add it to your custom cell class:
override func awakeFromNib() {
super.awakeFromNib()
let whiteRoundedView : UIView = UIView(frame: CGRect(x:10,y: 5,width: self.contentView.frame.size.width - 20,height: 117))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1,height: 1)
whiteRoundedView.layer.shadowOpacity = 0.2
let shadowPath = UIBezierPath(rect: whiteRoundedView.layer.bounds)
whiteRoundedView.layer.shouldRasterize = true
whiteRoundedView.layer.shadowPath = shadowPath.cgPath
self.contentView.addSubview(whiteRoundedView)
}
You are adding whiteRoundedView every time. If you are using a storyboard or Nib for designing your Cell UI then you can add whiteRoundedView there Or you can add a tag in whiteRoundedView and check if there are already any view added with that tag before adding the whiteRoundedView as subview.

Swift Change the tableviewcell border color according to data

I have written a code for making the cell border color change according to inStock or outStock , if it is inStock it will be red border else it would be green, but I it is not working for me, I put it in willDisplayCell and here is my code :
func tableView(_ tableView: UITableView,
willDisplay cell: UITableViewCell,
forRowAt indexPath: IndexPath){
cell.backgroundColor = UIColor.clear
cell.contentView.backgroundColor = UIColor.clear
let whiteRoundedView : UIView = UIView(frame: CGRect(x:10,y: 5,width: self.view.frame.size.width - 20,height: 214))
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 5.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1,height: 1)
whiteRoundedView.layer.borderWidth = 2
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
if stock[indexPath.row] == "inStock" {
whiteRoundedView.layer.borderColor = UIColor.red.cgColor
}
else {
whiteRoundedView.layer.borderColor = UIColor.green.cgColor
}
}
Try to move your code into cellForRowAt method like that
cell.layer.masksToBounds = true
cell.layer.cornerRadius = 5
cell.layer.borderWidth = 2
cell.layer.shadowOffset = CGSize(width: -1, height: 1)
let borderColor: UIColor = (stock[indexPath.row] == "inStock") ? .red : .green
cell.layer.borderColor = borderColor.cgColor
You are adding your whiteRoundedView multiple time for each cell - as cell instances are reused.
You should only create this once (when creating UITableViewCell) - and then manipulate color of it after that in willDisplayCell function.
I would suggest creating custom UITableViewCell, but you can also avoid that problem by using view "tag" property and checking if it exists already.