I added a change theme button in my main view controller where I have a tiny table view. I can change every color except a table view cell's Content View background color, and I can't access it outside cellForRowAt.
What should I do? Is there anyway to trigger a function from my custom Cell to change the color?
You can add a property in your controller to determine the color of the cells. When you wanna change the color, you call tableView.reloadData(). This will make cellForRowAt be called on each visible cell, and you can change color in this delegate method.
Your viewController
YourViewController: UIViewController {
fileprivate var cellColor = UIColor.blue
// where you change color
func changeColor() {
cellColor = UIColor.red
// this will make the delegate method `cellForRowAt` be called on each visible row
tableView.reloadData()
}
}
cellForRowAt:
// delegate method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuse id", for: indexPath) as! YourCustomCell
cell.contentView.backgroundColor = cellColor
// anything else...
return cell
}
You can achieve this by implementing delegate, if you have custom cell class and access the delegate method to change content view color.
Related
I have a UITableView that when a row is tapped a UIView pops up, everything is working fine but what I want is to be able to change the background color of the row when it's tapped to other color than the default gray. The standard behavior which is how I have it right now, behaves as follow, when I tap the row it changes the background color to gray and when I dismiss the popup UIView the background color changes back to the default white.
What I want is to be able to change the background color to blue when a row is tapped and changed it back to white when the UIView is dismissed.
I tried the following, which changes the color when the row is tapped but it doesn't change it back to white when the popup UIView is dismissed. In other words, it leaves the tapped rows with a blue background
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
/// Change color of the selected row
let selectedCell = tableView.cellForRow(at: indexPath)!
selectedCell.contentView.backgroundColor = UIColor.blue
}
How can I change the background of a cell when it's tapped and change it back to the default white when the popup UIView is dismissed?
FYI - I tried the didDeselectRowAt but it's never called.
Thanks
didDeselectRowAt is called when you tap another cell while the current is selected , you need to check viewDidAppear if the dismiss calles it or use a delegate otherwise and inside it add this code
tableView.visibleCells.forEach {
$0.backgroundColor = .white
}
try this you have to set selection style to none when you return cell cell.selectionStyle = .none
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Your identifier", for: indexPath)
cell.selectionStyle = .none
return cell
}
I need to place a radio button in tableview custom cell. whenever user clicks the tableview cell or button then radio button needs to work. I tried by using below code but didn't execute well.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! TableViewCell
cell.country.text = self.animals[indexPath.row]
cell.selectionStyle = UITableViewCellSelectionStyle.none;
if selectedRows.contains(indexPath)
{
cell.radioButton.setImage(UIImage(named:"check.png"), for: .normal)
}
else
{
cell.radioButton.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
return cell
}
Here's a great solution for creating radio buttons in a UITableView using a storyboard that requires zero code - and has 2 great Cool Tips!!
Make sure your table view is set to Single Selection, and to use Static cells.
Add a Basic cell, set the image to be your unchecked button image, and make sure the selection style is Default
Cool Tip # 1: Click on and select the cell's image view, and then set it's highlighted image to be your checked state. When the cell is highlighted or selected, the image view within will change to show its highlighted state.
Cool Tip # 2: Next, drag a UIView into the cell's content view, behind the text label. As you're using a basic cell, you won't be able to drop it directly into the cell, you'll need to drag it into onto the Document Outline on the left instead. Then hook this up to the cell's selected background view outlet. When a cell is selected (or highlighted), this view will be displayed in the background. In this case, we're going to use it to prevent the grey background appearing, so set its colour to Clear. Note that it doesn't matter what size the view is, and there's no need to set any constraints - it's automatically sized to match the cell at runtime.
Finally, duplicate this cell and change the text for each of your radio button options. Build and run, and you have code-free radio buttons!
In your TableViewCell class why don't you create a data source element and override the didSet for it. also in your data source for the UITableView I would recommend an array of something more than just a String.
I haven't compiled the below so this is just an idea.
import UIKit
class TableViewCell : UITableViewCell {
var data: Animal? {
didSet {
self.country.text = data.description
if (data.isSelected) {
self.radioButton.setImage(UIImage(named:"check.png"), for: .normal)
} else {
self.radioButton.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
}
}
}
in your view controller you will of course have to set the isSelected property whenever a row is tapped.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var animal = self.animals[indexPath.row]
animal.isSelected = !animal.isSelected
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! TableViewCell
cell.data = self.animals[indexPath.row]
}
and for your Animal maybe something like this:
struct Animal {
var description: String
var isSelected: Bool
}
I've got a collection view listing a bunch of videos and tapping any of them will push navigation controller which contain a custom player view to play the video. Tapping the close button on the customer player view will pop the current controller and go back to the video list controller.
Also when tapping one of the cells that cell will become gray color. When going back and tapping another cell from the video list, I want to deselect the previously selected cell and make it back to white and make the newly selected cell to be gray color.
The problem is, didDeselectCellAtIndexPath method is NEVER called. The previously selected cell does get deselected, which I could see from the print of the selected indexPath. However the delegation method never gets called thus backgroundColor never changes back to white. It looks like multiple cells are selected, despite allowsMultipleSesection is already set to false.
Following configuration is set:
let layout = UICollectionViewFlowLayout()
collectionView?.collectionViewLayout = layout
collectionView?.delegate = self
collectionView?.dataSource = self
collectionView?.allowsSelection = true
collectionView?.allowsMultipleSelection = false
Here is my collectionView methods and delegation methods:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! PreviewCell
cell.snapShotImageView.image = videoInfoArray[indexPath.item].previewImg
cell.durationLabel.text = videoInfoArray[indexPath.item].lengthText()
cell.dateLabel.text = videoInfoArray[indexPath.item].dateAddedText()
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! PreviewCell
cell.backgroundColor = UIColor.rgb(red: 240, green: 240, blue: 240)
let url = URL(fileURLWithPath: videoInfoArray[indexPath.item].path)
let vc = VideoController()
self.videoController = vc
vc.url = url
self.navigationController?.pushViewController(vc, animated: true)
}
override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! PreviewCell
cell.backgroundColor = UIColor.white
cell.captionFileLabel.backgroundColor = .white
print("Deselect called!!! This line should be printed, but it never happens!!!!")
}
Let the cell handle its background color.
Just add the following to your "PreviewCell" class:
override var isSelected: Bool {
didSet {
// TODO: replace .red & .blue with desired colors
backgroundColor = isSelected ? .red : .blue
}
}
If the parent Class doesn't implement a delegate method, any Subclass won't be able to do it either.
Please make sure the Class you are Subclassing implements it.
From the documentation I can understand that this method gets called when the user selected cell X, and then selects cell Y. Now cell X deselected and the method will be called.
Save an index of the selected cell before you move to the new view controller, and when you come back to the collection view controller, deselect the cell programmatically and then run inside your own function what you wanted to run in the deselect delegate method.
The collection view calls this method when the user tries to deselect an item in the collection view. It does not call this method when you programmatically deselect items.
If you do not implement this method, the default return value is true.
didDeselectItemAt is called when allowsMultipleSelection is set to true.
backgroundColor never changes back to white
even when your previously selected cell does get deselected, because your view doesnt get updated. You need to update your collection view cells view everytime you go back. You can refresh complete UICollectionView in viewWillAppear of your collectionViewController subclass. You can also use #entire method to deselect all selected indexPath.
At the end of your didSelectItemAt method, call the deselectItem(at:animated:) method on the collection view.
I a have 2 Buttons within my custom TableViewCell.
The Buttons are in bright colors. (BackgroundColor set)
However: Running the app - The Buttons color disappear and it becomes white:
I tried to programmatically change the color in viewDidLoad but Xcode doesn't react.
Any Ideas?
The heart of the problem is that you have introduced buttons but you are also setting the cell's textLabel!.text. You can't mix and match like that. If you're going to use a custom cell, you must use a completely custom cell.
Set the cell's type to Custom, drag a label into it, use a custom cell class, give it an outlet to the label, set this label's text, and all will be well.
Here's my custom cell with an outlet:
class MyCell : UITableViewCell {
#IBOutlet var label : UILabel!
}
Here's my cellForRow:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MyCell
cell.label.text = "Hi" // NOT cell.textLabel!.text
return cell
}
As you can see, the result is that button appears just fine.
You have an extra word in there:
cell.noButton.backgroundColor = UIColor.greenColor()
How can I achieve this screen with UITableViewCell and UITableViewController. With table section and header. Some ideas to achieve this?? Thanks!
What have you tried so far?
Your question seems a little broad.
You will need a set of custom UITableViewCell Subclasses, which you design in nibs.
To make the cells seem apart from each other, resize the content size of the Cells, and make the cell background another color.
Create a Segmented Control and add it to the Tableviews HeaderView.
For the FooterView it seems like this is some kind of subclassed Tabbar.
Easiest way to customise it in such a way, would be to create a View, and add buttons to it. Add this View as Subview to your TableViewController.
Have 2 UITableViewCell's one for each type i.e. 1 for showing the image and text and another for showing just the text.
Then in the cellForRowAt delegate method determine which to type to use based off the object you are data binding it to.
Example:
public final func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customObject = customObjects[indexPath.section]
switch customObject.type {
case .imageAndText:
if let cell = tableView.dequeueReusableCell(withIdentifier: ImageAndTextCell.identifier, for: indexPath) as? ImageAndTextCell {
cell.customObject = customObject
return cell
}
case .text:
if let cell = tableView.dequeueReusableCell(withIdentifier: TextCell.identifier, for: indexPath) as? TextCell {
cell.customObject = customObject
return cell
}
}
return UITableViewCell()
}