tableview image content selection color
Asked Answered
O

3

18

My app has a tableview with an image and a textfield:

  • image = image render as template image (light grey)
  • textfield = text color black

If I select a row, the color of both will change perfectly to white

Question - I change the image to a blue color image = render as default. If I now select a row, the text color of my textfield will change to white, but the image will stay blue.

I want the image change the color to white too but it doesn't.

What did I do wrong?

Example with an image render as template mode => default: grey | selected automatically white

enter image description here

Example with an colored image render as default mode => default: green | selected also green | expected white, but it stay green

enter image description here

Officious answered 28/8, 2017 at 15:40 Comment(10)
Isn't this same question? Respectively same solution? #33249956Lucier
i guess this is is not the same situation, isn't it?Officious
I'm not expert in macOS, but my guess is create custom subclass of NSTableCellView and in var selected in didSet handle by your own the highlighting or another related action.Lucier
is this the correct way? i can't believe that this is so complicatedOfficious
I really would like to say yes or no, but I don't know. This is just some way, how to do it. When you figure it out, if its correct or not, please write it here. I'm really curious.Lucier
could you provide your code? I just tested your scenario and it worked for meBaskerville
can you send my your example ? my example isn't available yet :(Officious
@Ghost108 Can you please show me show image of your expected output?Wristwatch
I updated my first post with an exampleOfficious
@Ghost108, did you find OSX solution?Warmongering
W
2

Try this:

    import Cocoa

class ViewController: NSViewController {
    @IBOutlet weak var tableView:NSTableView!
    var selectIndex = -1
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self

    }

    func tintedImage(_ image: NSImage, tint: NSColor) -> NSImage {
        guard let tinted = image.copy() as? NSImage else { return image }
        tinted.lockFocus()
        tint.set()

        let imageRect = NSRect(origin: NSZeroPoint, size: image.size)
        NSRectFillUsingOperation(imageRect, .sourceAtop)

        tinted.unlockFocus()
        return tinted
    }
}

extension ViewController:NSTableViewDataSource, NSTableViewDelegate{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 3
    }

    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?{


        let result = tableView.make(withIdentifier: "imageIcon", owner: self) as! NSTableCellView
        if selectIndex == row{
            result.imageView?.image = self.tintedImage(NSImage(named:"file")!, tint: NSColor.green)

        }else{
            result.imageView?.image = self.tintedImage(NSImage(named:"file")!, tint: NSColor.gray)

        }
        return result

    }

    func tableView(_ tableView: NSTableView, didAdd rowView: NSTableRowView, forRow row: Int) {
        if selectIndex == row{
            rowView.backgroundColor = NSColor.blue
        }else{
            rowView.backgroundColor = NSColor.clear
        }
    }


    func tableViewSelectionDidChange(_ notification: Notification) {
        let table = notification.object as! NSTableView
        self.selectIndex = tableView.selectedRow

        print(table.selectedRow);
        table.reloadData()
    }
}

Note: Change imageView tintColor color as per your requirement.

table row selection with color
Hope it will help you.

Wristwatch answered 10/9, 2017 at 17:38 Comment(6)
i need a osx solution :(Officious
unbelievable that a osx solution is so complicated. in iOS it is much easier :/Officious
Have you tried? Let me know if it is working or not.Wristwatch
yea i tried this a few days ago. this solution i found also on stack overflow. but i can't believe hat this have to be so much complicated. and i guess hat your code tableViewSelectionDidChange doesn't work. i tried this and if i put my outlineView.reloadData() in this function, the selection will always change by calling reloadData => loop :(Officious
@Ghost108 Don't call reloadData, check the documentation for a method to reload one cell.Cervix
Instead of reloadData, in tableViewSelectionDidChange use enumerateAvailableRowViewsUsingBlock: which operates only on the currently needed rows, not all, and is thus quite performant.Whinny
D
2

Create a custom cell and override the setHighlighted(_ highlighted: Bool, animated: Bool) to change the iamgeView's tintColor :

override func setHighlighted(_ highlighted: Bool, animated: Bool) {
    super.setHighlighted(highlighted, animated: animated)
    imageView?.tintColor = highlighted ? UIColor.white : UIColor.green
}

Then, when you create your cell, you set the image with an UIImageRenderingMode.alwaysTemplate:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = CustomCell()
    cell.imageView?.image = UIImage(named: "custom_image")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
    cell.imageView?.tintColor = UIColor.green
    return cell
}
Dakotadal answered 11/9, 2017 at 11:53 Comment(1)
and again: i need a osx solutionOfficious
S
2

Better late than never.

Here's my solution which a friend helped me with. Implement a custom NSImageCell class and override interiorBackgroundStyle:

#import <Cocoa/Cocoa.h>

NS_ASSUME_NONNULL_BEGIN

@interface TFSelectStateImageCell : NSImageCell

@end

NS_ASSUME_NONNULL_END
#import "TFSelectStateImageCell.h"

@implementation TFSelectStateImageCell


- (NSBackgroundStyle)interiorBackgroundStyle {
    NSBackgroundStyle style = [super interiorBackgroundStyle];
    self.image.template = (style == NSBackgroundStyleEmphasized);
    return style;
}

@end

This way you get the benefits of the template property for an NSImage when the row is selected, but when it's not selected, you get your full colour image.

Stevestevedore answered 23/9, 2021 at 22:7 Comment(2)
I could kiss you, my friend ... I was really struggling with this problem, and you saved the day :) Upvoted ... this should be the accepted answer.Assassin
Yup. it's a very simple solution, but something that's not so obvious.Stevestevedore

© 2022 - 2024 — McMap. All rights reserved.