UITableViewCell accessory not being tinted
Asked Answered
E

4

11

I've read multiple Q&A on the topic but none seem to work so here's my problem.

I created a custom UITableViewCell and in the Storyboard, I asked for there to be a disclosure indicator accessory. It is said that the tintColor should change the color of the indicator but after much research, here is what I found:

  • The cell's accessoryView maps out to a nil value therefore I cannot affect it's tintColor

I tried to create the accessoryView as done with a selectedBackgroundView like such:

self.accessoryView = UIView()

Obviously, it just creates a blank space and the original disclosure accessory disappears. I'm really confused with all this and cannot find a way to affect the color of a cell's accessory. Any help would be much welcome!

Expediential answered 15/1, 2015 at 1:27 Comment(0)
E
16

Here is what helped me and should help others.

The tintColor attribute of any UIView type and subtypes will propagate it's tint setting to the subviews in it's hierarchy. You could set the tintColor for a UITableView and it would be applied to all the cells within.

That said not all UITableViewCell Accessory types can unfortunately be tinted.

Those who get tinted:

  • UITableViewCellAccessoryCheckmark
  • UITableViewCellAccessoryDetailButton
  • UITableViewCellAccessoryDetailDisclosureButton -> only the Details part

The following do not get tinted:

  • UITableViewCellAccessoryDisclosureIndicator
  • UITableViewCellAccessoryDetailDisclosureButton -> only the Disclosure Button

So generally, you'll be able to change the color of your UITableViewCell Accessories. But if you want to change the grey arrow that usually indicates a segue to another view, no chance, it will stay grey.

The only way to change it is to actually create a custom UIAccessoryView. Here is one implementation purposefully broken down to keep it clear. Although I believe better ways exist:

In my custom UITableViewCell Class in the awakeFromNib() method

let disclosureImage = UIImage(named: "Disclosure Image")
let disclosureView = UIImageView(image: disclosureImage)
disclosureView.frame = CGRectMake(0, 0, 25, 25)
self.accessoryView = disclosureView

Be warned that this cannot be tinted either. It will have the color of the image used compared to "Tab Bar Items" so you might need multiple images for selected cells and unselected ones.

Expediential answered 15/1, 2015 at 19:35 Comment(1)
You can tint your disclosure image easily, using imageWithRendingMode & UIImageRenderingModeAlwaysTemplate. Then use tintColor on the UIImageView (or superview)Semantic
A
27

Extension

extension UITableViewCell {
    func prepareDisclosureIndicator() {
        for case let button as UIButton in subviews {
            let image = button.backgroundImageForState(.Normal)?.imageWithRenderingMode(.AlwaysTemplate)
            button.setBackgroundImage(image, forState: .Normal)
        }
    }
}

Swift 3 :

    extension UITableViewCell {
        func prepareDisclosureIndicator() {
            for case let button as UIButton in subviews {
            let image = button.backgroundImage(for: .normal)?.withRenderingMode(.
                alwaysTemplate)
            button.setBackgroundImage(image, for: .normal)
        }
    }
}

Do it

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.prepareDisclosureIndicator()
}

swift 3 :

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.prepareDisclosureIndicator()
    
}

Objective-C:

for (UIView *subview in cell.subviews) {
    if ([subview isMemberOfClass:[UIButton class]]) {
        UIButton *button = (UIButton *)subview;
        UIImage *image = [[button backgroundImageForState:UIControlStateNormal] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        [button setBackgroundImage:image forState:UIControlStateNormal];
    }
}
Aphis answered 21/3, 2016 at 23:37 Comment(3)
thanks. Nice, clean and easy. Anyone wanting to know how to set a colour other then default blue. Just set the tintColor for "button", "button.tintColor = .redColor()"Krusche
tintColor did not work for me, but the code above didConsuetudinary
This worked for me. I set the desired tint color on my UITableViewCell. Zelko's code causes the disclosure indicator to "inherit" that tint color.Chartism
E
16

Here is what helped me and should help others.

The tintColor attribute of any UIView type and subtypes will propagate it's tint setting to the subviews in it's hierarchy. You could set the tintColor for a UITableView and it would be applied to all the cells within.

That said not all UITableViewCell Accessory types can unfortunately be tinted.

Those who get tinted:

  • UITableViewCellAccessoryCheckmark
  • UITableViewCellAccessoryDetailButton
  • UITableViewCellAccessoryDetailDisclosureButton -> only the Details part

The following do not get tinted:

  • UITableViewCellAccessoryDisclosureIndicator
  • UITableViewCellAccessoryDetailDisclosureButton -> only the Disclosure Button

So generally, you'll be able to change the color of your UITableViewCell Accessories. But if you want to change the grey arrow that usually indicates a segue to another view, no chance, it will stay grey.

The only way to change it is to actually create a custom UIAccessoryView. Here is one implementation purposefully broken down to keep it clear. Although I believe better ways exist:

In my custom UITableViewCell Class in the awakeFromNib() method

let disclosureImage = UIImage(named: "Disclosure Image")
let disclosureView = UIImageView(image: disclosureImage)
disclosureView.frame = CGRectMake(0, 0, 25, 25)
self.accessoryView = disclosureView

Be warned that this cannot be tinted either. It will have the color of the image used compared to "Tab Bar Items" so you might need multiple images for selected cells and unselected ones.

Expediential answered 15/1, 2015 at 19:35 Comment(1)
You can tint your disclosure image easily, using imageWithRendingMode & UIImageRenderingModeAlwaysTemplate. Then use tintColor on the UIImageView (or superview)Semantic
N
0

Here's the Objective-C version of Tokuriku's answer for us dinosaurs:

    UIImageSymbolConfiguration *configuration = [UIImageSymbolConfiguration configurationWithPointSize:15.0f weight:UIImageSymbolWeightUnspecified];
    UIImageView *disclosureView = [[UIImageView alloc] initWithImage:[[UIImage systemImageNamed:@"chevron.right" withConfiguration:configuration] imageWithRenderingMode: UIImageRenderingModeAlwaysTemplate]];
    disclosureView.frame = CGRectMake(0, 0, 15, 15);
    disclosureView.tintColor = UIColor.systemYellowColor;
    cell.accessoryView = disclosureView;

You can use the system image named: "chevron.right" to avoid creating your own. The frame size given here seems to give an image which is closure to the native Apple image size.

Also be careful to set cell.accessoryView to nil for other cells where you intend to use the standard accessory types

    cell.accessoryType = self.somePreference ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    cell.accessoryView = nil;
Nato answered 9/3, 2021 at 4:2 Comment(0)
L
0

Swift 5, iOS 13 and above:

cell.tintColor = .white
cell.accessoryView = UIImageView(image: UIImage(systemName: "chevron.right"))

You can customize arrow:

let config = UIImage.SymbolConfiguration(pointSize: 17, weight: .bold)
let image = UIImage(systemName: "chevron.right", withConfiguration: config)
cell.accessoryView = UIImageView(image: image)
Leeway answered 4/12, 2023 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.