6

I'm trying to add template images to the slide menu controller (based on this SideMenuController component). But I have an issue with tint color. Original images are dark grey, and I want them to be white. I've set .alwaysTemplate mode and tint colors programmatically, but instead of required behaviour I am getting this:

enter image description here

I.e., tint color changes from grey to white only when I am tapping that menu item. Do you know how to fix that?

Here is a code I have for navigation menu controller:

class NavigationMenuController: UITableViewController {

    @IBOutlet weak var groupsIcon: UIImageView!
    @IBOutlet weak var calendarIcon: UIImageView!
    @IBOutlet weak var documentsIcon: UIImageView!
    @IBOutlet weak var settingsIcon: UIImageView!

    private let gradientTop = UIColor.fromHexadecimal(0xF3736F)
    private let gradientBottom = UIColor.fromHexadecimal(0xEC92AE)
    private let cellSelection = UIColor.fromHexadecimal(0xEC92AE)
    private let menuIconTint = UIColor.fromHexadecimal(0xFFFFFF)

    private let segues = [
        "embedGroupsController",
        "embedCalendarController",
        "embedRulesController",
        "embedSettingsController"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        let gradient = CAGradientLayer()
        gradient.colors = [gradientTop.cgColor, gradientBottom.cgColor]
        gradient.locations = [0.0, 1.0]
        gradient.frame = tableView.bounds

        let backgroundView = UIView(frame: tableView.bounds)
        backgroundView.layer.insertSublayer(gradient, at: 0)
        tableView.backgroundView = backgroundView

        let imageViews: [UIImageView] = [groupsIcon, calendarIcon, documentsIcon, settingsIcon]
        for imageView in imageViews {
            guard let image = imageView.image else { fatalError("Image not found") }
            let templateImage = image.withRenderingMode(.alwaysTemplate)
            imageView.image = templateImage
            imageView.tintColor = menuIconTint
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAt: indexPath)
        let bgColorView = UIView()
        bgColorView.backgroundColor = cellSelection
        cell.selectionStyle = .default
        cell.backgroundColor = .clear
        cell.selectedBackgroundView = bgColorView
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let sideMenu = sideMenuController else {
            fatalError("Side menu controller is not configured")
        }
        if indexPath.row >= segues.count {
            fatalError("Unexpected row index: \(indexPath.row)")
        }
        sideMenu.performSegue(withIdentifier: segues[indexPath.row], sender: nil)
    }

}

I also tried to do it via Storyboard and Assets settings, but having same effect. I am running this app on iOS 10 and Swift 3.

devforfu
  • 1,570
  • 1
  • 19
  • 41
  • 1
    This might help https://stackoverflow.com/questions/6745919/uitableviewcell-subview-disappears-when-cell-is-selected – Aakash Jun 14 '17 at 10:10
  • you are setting white tintcolor of image on selection but on selecting another cell you have to reset previously selected cell. so u have to set back tintColor to dark Grey for previously selected cell – Hitesh Agarwal Jun 14 '17 at 10:48
  • @HiteshAgarwal No, I mean, that I want to have them all be white, and none grey. But it happens only after clicking. They all should be unconditionally white. – devforfu Jun 14 '17 at 11:20
  • 1
    then use white icons or set white tint color in cellForRowAtIndexPath – Hitesh Agarwal Jun 15 '17 at 04:58
  • @HiteshAgarwal But I have already set tint color in `viewDidLoad()`. Do you think it should be set each time cellForRowAtIndexPath called? I just can't figure out why UIImageView ignores tint color first time, and takes into account after selection. – devforfu Jun 16 '17 at 05:48
  • @Aakash Do you think I should override those methods and each time reset `tintColor` property? – devforfu Jun 16 '17 at 05:50
  • Everytime the cell is selected tintColor is changed but remember cells are reused to you should better set the tintColor in cellForRow. Alternatively, you can make use of cell's prepare for reuse method and set the default values for the cell properties there – Aakash Jun 16 '17 at 07:18
  • You can use `tintAdjustmentMode` on ImageView. Try to set this to `normal` – G. Veronika Feb 07 '19 at 10:44

2 Answers2

5

I had the same issues with a UIImageView tint inside a cell.

I fixed it by setting the image view tint to Default and setting the cell's content view tint instead.

Rivera
  • 10,792
  • 3
  • 58
  • 102
2

Ok, yes, @Aakash and @HiteshAgarwal are right, here is a solution to my problem. I set tint color in cellForRowAt delegate method and it changed to required color (though I still do not know why Storyboard approach failed and why manual color setting is required):

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = super.tableView(tableView, cellForRowAt: indexPath)
    let bgColorView = UIView()

    bgColorView.backgroundColor = cellSelection
    cell.selectionStyle = .default
    cell.backgroundColor = .clear
    cell.selectedBackgroundView = bgColorView

    if let imageView = getCellImageView(cell) {
        imageView.tintColor = UIColor.white
    }

    return cell
}
devforfu
  • 1,570
  • 1
  • 19
  • 41