9

What is the best way to change the color of NSProgressIndicator, is there an easier way than just to subclass it and then draw the whole component by myself?

Basically what I want to do is to have a similar component but with the ability to change the color of the bar.

I tried to google this but all the questions were quite outdated and didn't really concern the 10.10 OS X version that I am working on. Also checked cocoa controls and did only find 1 component that was for outdated OS X version.

Samuli Lehtonen
  • 3,840
  • 5
  • 39
  • 49

8 Answers8

17

You can use Quartz filters (e.g. hue adjust) for this directly in Interface Builder. This works better than expected.

NSProgressIndicator

It's in the Effects Inspector. Under "Content Filters" you can add "Hue Adjust"

enter image description here

Schuuure
  • 301
  • 2
  • 10
paxos
  • 877
  • 5
  • 11
1

Use "CIFalseColor" filter to get white color and more.

let colorFilter = CIFilter(name: "CIFalseColor")!
colorFilter.setDefaults()
colorFilter.setValue(color1, forKey: "inputColor0")
colorFilter.setValue(color2, forKey: "inputColor1")
proggressBar?.contentFilters = [colorFilter]
KamyFC
  • 858
  • 9
  • 17
  • How do you set the values for color1 and color2 ? – Death Guard Feb 05 '20 at 11:20
  • let color1 = NSColor(red: 99.0, green: 0.0, blue: 0.0, alpha: 1.0) and similarly for color 2 – KamyFC Feb 10 '20 at 06:44
  • Okay, I've been messing around with this for a while. I have defined inputColor0 and inputColor1 through the IB as False Color Content Filter. How would I go about flipping/inverting the two colors. Say my progressBar reaches a certain point, inputColor1 would then become the color of the progressBar. – SouthernYankee65 Sep 24 '20 at 21:22
1

I was trying to change de Hue as seen in most answers, but I was getting a lot of issues to get the right specific color I wanted.

What did worked for me, and seems to be the most direct way to get a specific color, was using the CIColorMonochrome filter, where You can set any RGB color you want:

enter image description here

let myCustomColor: CIColor(red: 10, green: 10, blue: 10)
if let colorMonochrome = CIFilter(name: "CIColorMonochrome", parameters: [kCIInputColorKey: myCustomColor]) {
    progressIndicator.contentFilters.append(colorMonochrome)
}
0

To change color of NSProgressIndicator use setControlTint: method. If you want to set custom color you have to draw such control manually. However, you should use the system color to keep this kind of control consistent across the system.

Tomasz Szulc
  • 4,217
  • 4
  • 43
  • 79
0

For Swift the method name is controlTint.

progressIndicator = NSProgressIndicator(frame: .......
progressIndicator.controlTint = .blueControlTint
anothernode
  • 5,100
  • 13
  • 43
  • 62
AlexG
  • 1
  • 1
0

you can use proggressBar.appearance = NSAppearance(named: .vibrantLight) // this is light or vibrantDark for "black" indictor

ankmara
  • 265
  • 3
  • 13
0

Based on Paxos' answer on the Interface builder, this is how I was able to do it programmatically:

let progress = NSProgressIndicator()
progress.contentFilters = [CIFilter(name: "CIHueAdjust", parameters: ["inputAngle": 4])!] 

This would turn the bar green. I got this from looking at the Main.storyboard diff:

<progressIndicator maxValue="100" doubleValue="50" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="NIr-vo-obX">
  <rect key="frame" x="3" y="22" width="210" height="20"/>
+ <contentFilters>
+  <ciFilter name="CIHueAdjust">
+   <configuration>
+    <real key="inputAngle" value="4"/>
+    <null key="inputImage"/>
+   </configuration>
+  </ciFilter>
+ </contentFilters>
</progressIndicator>
Brando
  • 11
  • 2
0

Based on the answer from KamyFC I found out that CIColor was required for the filter named "CIFalseColor".

Here is the Objective-C solution to make the progress bar whatever NSColor, in this example orange. Don't forget to add @import Quartz; to your file.

// Create color:
CIColor *color = [[CIColor alloc] initWithColor:[NSColor orangeColor]];

// Create filter:
CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor"
                             withInputParameters:@{@"inputColor0" : color,
                                                   @"inputColor1" : color}];

// Assign to bar:
_progressBar.contentFilters = @[colorFilter];
Martijn
  • 429
  • 4
  • 13