Change text color in tableview cell in didHighlightRowAt - ios

I have this code:
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell!.contentView.backgroundColor = .blue
cell?.textLabel?.textColor = UIColor.white
var cell2 = tableView.cellForRow(at: indexPath) as! DataTableViewCell
cell2.textLabel.textColor = UIColor.white
}
The background change works fine, but the text color change does not work.
Does anyone know why and how to fix this problem?

I think instead of writing these two lines:
cell!.textLabel?.textColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
cell?.textLabel?.textColor = UIColor.white
writing only a single line as:
cell.textLabel?.highlightedTextColor = .black
will work fine for you!

Use this function in your DataTableViewCell
func setHighlighted(_ highlighted: Bool,
animated: Bool)
See Apple Developer Documentation

Try any one of these:
// set highlighted color in `tableView cellForRowAt indexPath`
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell?.textLabel?.highlightedTextColor = UIColor.white
}
or try this
class CustomCell: UITableViewCell {
// As an alternate of `tableView cellForRowAt indexPath`, label text highlighted color can be set in both these methods of cell - `awakeFromNib` and `prepareForReuse`
override func awakeFromNib() {
super.awakeFromNib()
self.textLabel?.highlightedTextColor = UIColor.white
}
override func prepareForReuse() {
super.prepareForReuse()
self.textLabel?.highlightedTextColor = UIColor.white
}
// or textColor can be directly set here
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
self.textLabel?.textColor = UIColor.white
}
}

The tableView(_:didHighlightRowAt:) function is part of the Controller domain of your app while setting colors is part of the View domain (as per Model—View—Controller pattern). To keep up a good separation of responsibilities you might want to consider changing colors outside of the controller, i. e. in the cell itself. For this to work, you would create a simple UITableViewCell subclass, like so:
class MyCell: UITableViewCell {
class var reuseIdentifier: String { return "MyCell" }
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if selected {
textLabel?.textColor = UIColor.white
} else {
textLabel?.textColor = UIColor.black
}
}
}
This way the cell itself (instead of the controller) handles its own graphical representation which is the recommended way.

cell.textLabel.highlightedTextColor = [UIColor greencolor];

OK, this code works:
override func awakeFromNib () {
         super.awakeFromNib ()
         // Initialization code
         self.titleCell? .xtxtColor = UIColor.black
         self.titleCell? .highlightedTextColor = UIColor.white
  }
     override func setSelected (_ selected: Bool, animated: Bool) {
         super.setSelected (selected, animated: animated)
         // Configure the view for the selected state
     }
    
    
     override func prepareForReuse () {
         super.prepareForReuse ()
         self.titleCell? .highlightedTextColor = UIColor.white
     }
Thank you very much for your help :)

Related

UITableViewCell selection backgroundColor change not working

I have a custom UITableViewCell class that looks like this:
class CustomTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
print("Selected: ", selected)
if selected {
self.backgroundColor = .red
} else {
self.backgroundColor = .white
}
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
print("Highlighted: ", highlighted)
if highlighted {
self.backgroundColor = .red
} else {
self.backgroundColor = .white
}
}
And then in my UITableViewDelegate I added this code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// Navigate to the next screen
}
However, both print() statements are always false. And the backgroundColor never changes. Anything I'm doing wrong here?
Remove all other code just replace your UITableViewCell class with this
class CustomTableViewCell: UITableViewCell {
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
self.backgroundColor = selected ? .red : .white
}
}
I figured out the two issue in your code. Please refer below issue along with the solution.
Please use the below code to set background color of UITableViewCell
self.contentView.backgroundColor = .red
Instead of
self.backgroundColor = .red
Just replace didSelectRowAt method if want to change color permanently otherwise keep as it is.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
Refer below attached source code of the demo application. If any further help required.
Source Code

design UI of app using tablview in swift

I want UI of my app to be similar like as shown in below image.
Using tableview i'm able to get Payment,Delivery,Build Team options as shown in image but for Build Profile,Manage Menu.. how do i do it using tableview ?
If not tableview for these options then what other control i can try.
this type of UI you are looking for and you can easily get by creating different Cell classes
UI Output :
Required Code
Step 1 - Create different Xib of table cell
class viewWithArrow: UITableViewCell {
#IBOutlet weak var headerLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
class viewWithShadow: UITableViewCell {
#IBOutlet weak var shadowView: UIView!{
didSet{
shadowView.addShadowToView(color: .black)
}
}
#IBOutlet weak var headerLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Adding Shadow Effect :
extension UIView {
func addShadowToView(color:UIColor)
{
self.layer.shadowColor = color.cgColor
self.layer.shadowOpacity = 0.2
self.layer.masksToBounds = false
self.clipsToBounds = false
self.layer.shadowOffset = CGSize(width: 0, height: 0)
self.layer.shadowRadius = 5
}
}
View controller
class ViewController: UIViewController
{
var dataArray : [String] = ["11","22","33","44","55","66"]
#IBOutlet weak var homeVcTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
homeVcTableView.register(UINib(nibName: "viewWithShadow", bundle: nil), forCellReuseIdentifier: "viewWithShadow")
homeVcTableView.register(UINib(nibName: "viewWithArrow", bundle: nil), forCellReuseIdentifier: "viewWithArrow")
}
override func viewWillAppear(_ animated: Bool) {
self.homeVcTableView.delegate = self
self.homeVcTableView.dataSource = self
}
}
extension ViewController : UITableViewDataSource, UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0,1:
let cell = self.homeVcTableView.dequeueReusableCell(withIdentifier: "viewWithShadow", for: indexPath) as! viewWithShadow
cell.headerLabel.text = dataArray[indexPath.row]
return cell
default:
let cell = self.homeVcTableView.dequeueReusableCell(withIdentifier: "viewWithArrow", for: indexPath) as! viewWithArrow
cell.headerLabel.text = dataArray[indexPath.row]
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.homeVcTableView.frame.size.height*0.1
}
}
Working code link - https://drive.google.com/open?id=18mSlWAU_e4XElox4H-oTpqg8clD_HKwu

Making custom UITableView Cells Display Contents Properly (Not Blank)

I have been working on making an iOS app which requires a screen/view that is scrollable and has an image, then a list and then an image and then another image (attached is the screenshot from the Android version I made)
Top of the view
View Scrolled
I have tried using the following code, which gives me the correct amount of cells but they are all blank.
//
// ServicesTableViewController.swift
// Contact Australis
//
// Created by Raghav Khanna on 22/4/18.
// Copyright © 2018 Australis. All rights reserved.
//
import UIKit
class ServiceViewCell: UITableViewCell {
#IBOutlet weak var IMage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
IMage.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
class ServiceViewCellList: UITableViewCell {
#IBOutlet weak var somethin_label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let color = UIColor(red: 0/255, green: 105/255, blue: 191/255, alpha: 1.0).cgColor
let back_colour = UIColor(red: 212/255, green: 242/255, blue: 253/255, alpha: 1.0).cgColor
let back_colour_ui = UIColor(red: 212/255, green: 242/255, blue: 253/255, alpha: 1.0)
let radius: CGFloat = 5
let border_width:CGFloat = 1.5
somethin_label.layer.borderColor = color
somethin_label.layer.borderWidth = border_width
somethin_label.layer.cornerRadius = radius
somethin_label.backgroundColor = back_colour_ui
}
var items_maintenance = ["Painting","All Lighting & Globe Replacemt",
"Carpet & Hard Floor Replacement","Electrical Work & Maintenance","Plumbing Work & Maintenance","Test & Tag Completion","Office Furniture Removal", "Hard Waste Removal", "Window Frosting", "All Other Handy Man & Maintenance Tasks"]
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
} class ServiceViewCellCleaning: UITableViewCell {
#IBOutlet weak var Title: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
Title.frame = CGRect(x: 0, y: 0, width: 100, height: 200)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
class ServiceViewCellCleaningList: UITableViewCell {
#IBOutlet weak var other_label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let color = UIColor(red: 0/255, green: 105/255, blue: 191/255, alpha: 1.0).cgColor
let back_colour = UIColor(red: 212/255, green: 242/255, blue: 253/255, alpha: 1.0).cgColor
let back_colour_ui = UIColor(red: 212/255, green: 242/255, blue: 253/255, alpha: 1.0)
let radius: CGFloat = 5
let border_width:CGFloat = 1.5
other_label.layer.borderColor = color
other_label.layer.borderWidth = border_width
other_label.layer.cornerRadius = radius
other_label.backgroundColor = back_colour_ui
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
class ServicesTableViewController: UITableViewController {
let basicCellIdentifier = "BasicCell"
var items_maintenance = ["Painting","All Lighting & Globe Replacement", "Carpet & Hard Floor Replacement","Electrical Work & Maintenance","Plumbing Work & Maintenance","Test & Tag Completion","Office Furniture Removal", "Hard Waste Removal", "Window Frosting", "All Other Handy Man & Maintenance Tasks"]
var items_cleaning = ["All Genral Comercial Cleaning","Office Cleaning", "Initial Clean","Spring Clean","Steam Carpet Cleaning","Window Washing","High Pressure Washing", "Waste Removal", "Strip & Seal Hard Floors", "Scrubbing & Buffing Hard Floors"]
let cellSpacingHeight: CGFloat = 5
#IBOutlet var table: UITableView!
func configureTableView() {
//tableView.rowHeight = UITableViewAutomaticDimension
//tableView.estimatedRowHeight = 1000.0
//let rect = CGRect(origin: .zero, size: CGSize(width: 400, height: 400))
//self.tableView = UITableView(frame: rect, style: UITableViewStyle.plain)
table.register(ServiceViewCell.self, forCellReuseIdentifier: "maintenance")
table.register(ServiceViewCellList.self, forCellReuseIdentifier: "customcell")
table.register(ServiceViewCellCleaning.self, forCellReuseIdentifier: "cleaning")
table.register(ServiceViewCellCleaningList.self, forCellReuseIdentifier: "cleaning_customcell")
}
/*func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return
}*/
override func viewDidLoad() {
super.viewDidLoad()
self.configureTableView()
table.reloadData()
table.delegate = self
table.dataSource = self
// Uncomment the following line to preserve selection between presentations
self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 4
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else if section == 1 {
return items_maintenance.count
} else if section == 2 {
return 1
}
else {
return items_cleaning.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let maintenance_title = table.dequeueReusableCell(withIdentifier: "maintenance", for: indexPath) as! ServiceViewCell
let maintenance_list = table.dequeueReusableCell(withIdentifier: "customcell", for: indexPath) as! ServiceViewCellList
let cleaning_title = table.dequeueReusableCell(withIdentifier: "cleaning", for: indexPath) as! ServiceViewCellCleaning
let cleaning_list = table.dequeueReusableCell(withIdentifier: "cleaning_customcell", for: indexPath) as! ServiceViewCellCleaningList
maintenance_list.somethin_label?.text = self.items_maintenance[indexPath.row]
maintenance_list.somethin_label?.adjustsFontSizeToFitWidth = false
maintenance_list.somethin_label?.font = UIFont.systemFont(ofSize: 10.0)
cleaning_list.other_label?.text = "test"
cleaning_list.other_label?.adjustsFontSizeToFitWidth = false
cleaning_list.other_label?.font = UIFont.systemFont(ofSize: 10.0)
cleaning_title.Title?.image = UIImage(named: "cleaning.png")
maintenance_title.IMage?.image = UIImage(named: "maintenance.png")
if indexPath.section == 0 {
return maintenance_title
} else if indexPath.section == 1 {
return maintenance_list
} else if indexPath.section == 2 {
return cleaning_title
}
else {
return cleaning_list
}
return cleaning_list
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
//Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return false
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
My Storyboard looks like this (Its another view in the main storyboard with for prototype cells with custom classes) and I am struggling to figure out why I keep getting either "Unexpectedly found nil while unwrapping an Optional value" for "maintenance_list.somethin_label!.text = self.items_maintenance[indexPath.row]" or this (blank cells) when I use '?' instead of '!'.
I know why I don't get the nil while unwrapping error when using the '?'. But the real problem is why I am not being able to interact with the views in each of the cells to display the desired data. I have checked all the outlets, and they are all correct.
Any help would be greatly appreciated.
Thanks in advance.
Without having access to the entire project is difficult to say why it's not working.
But I think the approach you are following is not correct, you should look into having only two sections (Maintenance, Cleaning) and then each item of Maintenance and Cleaning would be a cell, so your datasource should return 2 sections and 10 rows for each section.
You would need a section header, which would have an image view, and then only one prototype cell, that you can reuse for any row.
Hope this helps.

Whole UITableviewcell is highlighted instead of rounded view inside the cell

I was trying to achieve the rounded tableview cell effect, so I tried to mess with layoutSubviews in my custom cell class:
override func layoutSubviews() {
// Set the width of the cell
self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width - 40, self.bounds.size.height)
super.layoutSubviews()
}
I heard that it is not recommended to change the width of the cell itself, and that adding a UIView (called mainView in the code) to the cell and adding constraints + corner radius would do the job.
My custom cell class is now:
class customTableViewCell: UITableViewCell {
#IBOutlet weak var mainView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
mainView.layer.borderWidth = 2
mainView.layer.cornerRadius = 20
mainView.layer.borderColor = UIColor.black.cgColor
mainView.layer.masksToBounds = true
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
and here are the relevant components to my ViewController that holds the mainTableView:
override func viewDidLoad() {
super.viewDidLoad()
mainTableView.rowHeight = 100
mainTableView.backgroundColor = UIColor.clear
mainTableView.delegate = self
mainTableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.mainTableView.dequeueReusableCell(withIdentifier: "customCell") as! customTableViewCell
// note that indexPath.section is used rather than indexPath.row
cell.textLabel?.text = self.animals[indexPath.row]
cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 16)
cell.textLabel?.textAlignment = .center
// add border and color
cell.backgroundColor = UIColor.clear
cell.layer.borderColor = UIColor.clear.cgColor
cell.layer.borderWidth = 1
//cell.layer.cornerRadius = 8
cell.clipsToBounds = true
return cell
}
My result is this:
screenshot of simulator
As you can tell, the whole cell is highlighted and not just what is inside.
My remaining question is - Is there a way to make only the UIView inside the contentView of the cell to be highlighted instead of the whole cell? Or should I just not enable selection and highlighting.
Please let me know. Thanks.
For Swift 4.1, in your tableView(_ tableView: UITableView, cellForRowAt...) or Storyboard tableview cell scene:
cell.selectionStyle = .none
in your cell subclass:
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
// do your custom things with the cell subviews here
if highlighted == true {
self.contentView.backgroundColor = .gray
} else {
self.contentView.backgroundColor = .white
}
}
You can achieve the desire effect. You just have to follow these steps.
Step 1 - Set your tableview cell's selection style to UITableViewCellSelectionStyleNone
cell.selectionStyle = UITableViewCellSelectionStyleNone;
Step 2 - In your customTableViewCell, override the default implementation of setHighlighted(_:animated:) and decide what you are going to highlight.
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
self.backgroundColor = UIColor.blue // Change this to any color you want.
}
You can also highlight individual elements of your custom UITableViewCell in this method.
I hope this helps.

Create several buttons

I want to create 10 buttons in the ViewController. These buttons move the user to the next ViewController. If I use a storyboard, do I have to create 10 buttons or is there an easier way to solve the problem?
It should also satisfy following conditions:
my button into cell won't be gray or another colour. But I need to my button will be selected and change colour.
If I use the tableView and press the button, the selected cell fills up with a gray color. I want to select only the button. (Tableview should not show gray color for selection)
Here is sample code as solution to your problem (it's working according to your requirement, just copy and paste in your view controller)
import UIKit
class ViewController2: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblTable: UITableView!
var buttonTitles = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"]
override func viewDidLoad() {
super.viewDidLoad()
tblTable.delegate = self
tblTable.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return buttonTitles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "buttoncell") as! ButtonCell
let buttonTitle: String = buttonTitles[indexPath.row]
cell.btnButton.setTitle(buttonTitle, for: .normal)
cell.btnButton.tag = indexPath.row
cell.btnButton.addTarget(self, action: #selector(self.buttonClick(button:)), for: .touchUpInside)
cell.selectionStyle = .none
return cell
}
#objc func buttonClick(button: UIButton) -> Void {
print("btnButton clicked at index - \(button.tag)")
button.isSelected = !button.isSelected
if button.isSelected {
button.backgroundColor = UIColor.green
} else {
button.backgroundColor = UIColor.yellow
}
}
}
class ButtonCell: UITableViewCell {
#IBOutlet var btnButton: UIButton!
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
if selected {
btnButton.backgroundColor = UIColor.green
} else {
btnButton.backgroundColor = UIColor.yellow
}
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
if highlighted {
btnButton.backgroundColor = UIColor.green
} else {
btnButton.backgroundColor = UIColor.yellow
}
}
}
And Snapshot of storyboard layout with tableview and cell interface design
Here is result (working behavior of button) in simulator
I think, this is enough to solve your problem.

Resources