Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a gradient tint color to a UISlider in XCode 6?

I'm working on a design application that has a section for selecting colors by three sliders for RGB. As we can see in xcode, where we want to select a color by RGB values, the slider tint color is a gradient color that changes when we change the sliders. I want to use this in my application. but I have no idea about how to do this?

I've found this code in a blog. but didn't work for me.

- (void)setGradientToSlider:(UISlider *)Slider WithColors:(NSArray *)Colors{

    UIView * view = (UIView *)[[Slider subviews]objectAtIndex:0];

    UIImageView * maxTrackImageView = (UIImageView *)[[view subviews]objectAtIndex:0];

    CAGradientLayer * maxTrackGradient = [CAGradientLayer layer];
    CGRect rect = maxTrackImageView.frame;
    rect.origin.x = view.frame.origin.x;

    maxTrackGradient.frame = rect;
    maxTrackGradient.colors = Colors;

    [maxTrackGradient setStartPoint:CGPointMake(0.0, 0.5)];
    [maxTrackGradient setEndPoint:CGPointMake(1.0, 0.5)];

    [[maxTrackImageView layer] insertSublayer:maxTrackGradient atIndex:0];

    /////////////////////////////////////////////////////

    UIImageView * minTrackImageView = (UIImageView *)[[view subviews]objectAtIndex:1];

    CAGradientLayer * minTrackGradient = [CAGradientLayer layer];
    rect = minTrackImageView.frame;
    rect.size.width = maxTrackImageView.frame.size.width;
    rect.origin.x = 0;
    rect.origin.y = 0;

    minTrackGradient.frame = rect;
    minTrackGradient.colors = Colors;

    [minTrackGradient setStartPoint:CGPointMake(0.0, 0.5)];
    [minTrackGradient setEndPoint:CGPointMake(1.0, 0.5)];

    [minTrackImageView.layer insertSublayer:minTrackGradient atIndex:0];

}

I would appreciate any helps. Thanks.

like image 527
hmak.me Avatar asked Jan 15 '15 15:01

hmak.me


3 Answers

While it didnt give me the desired results here is a down and dirty Swift version of the answer above for those that want to try it.

func setSlider(slider:UISlider) {

    let tgl = CAGradientLayer()
    let frame = CGRectMake(0, 0, slider.frame.size.width, 5)
    tgl.frame = frame
    tgl.colors = [UIColor.blueColor().CGColor, UIColor.greenColor().CGColor, UIColor.yellowColor().CGColor, UIColor.orangeColor().CGColor, UIColor.redColor().CGColor]
    tgl.startPoint = CGPointMake(0.0, 0.5)
    tgl.endPoint = CGPointMake(1.0, 0.5)

    UIGraphicsBeginImageContextWithOptions(tgl.frame.size, tgl.opaque, 0.0);
    tgl.renderInContext(UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    image.resizableImageWithCapInsets(UIEdgeInsetsZero)

    slider.setMinimumTrackImage(image, forState: .Normal)
    //slider.setMaximumTrackImage(image, forState: .Normal)

}

UPDATE for Swift 4.0

func setSlider(slider:UISlider) {
    let tgl = CAGradientLayer()
    let frame = CGRect.init(x:0, y:0, width:slider.frame.size.width, height:5)
    tgl.frame = frame
    tgl.colors = [UIColor.blue.cgColor, UIColor.green.cgColor, UIColor.yellow.cgColor, UIColor.orange.cgColor, UIColor.red.cgColor]
    tgl.startPoint = CGPoint.init(x:0.0, y:0.5)
    tgl.endPoint = CGPoint.init(x:1.0, y:0.5)

    UIGraphicsBeginImageContextWithOptions(tgl.frame.size, tgl.isOpaque, 0.0);
    tgl.render(in: UIGraphicsGetCurrentContext()!)
    if let image = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()

        image.resizableImage(withCapInsets: UIEdgeInsets.zero)

        slider.setMinimumTrackImage(image, for: .normal)
    }
}
like image 156
DogCoffee Avatar answered Oct 08 '22 04:10

DogCoffee


Here is possible solution:

Usage:

//array of CGColor objects, color1 and color2 are UIColor objects 
NSArray *colors = [NSArray arrayWithObjects:(id)color1.CGColor, (id)color2.CGColor, nil];
//your UISlider
[slider setGradientBackgroundWithColors:colors];

Implementation:

Create category on UISlider:

- (void)setGradientBackgroundWithColors:(NSArray *)colors
{
    CAGradientLayer *trackGradientLayer = [CAGradientLayer layer];
    CGRect frame = self.frame;
    frame.size.height = 5.0; //set the height of slider
    trackGradientLayer.frame = frame;
    trackGradientLayer.colors = colors;
    //setting gradient as horizontal
    trackGradientLayer.startPoint = CGPointMake(0.0, 0.5);
    trackGradientLayer.endPoint = CGPointMake(1.0, 0.5);

    UIImage *trackImage = [[UIImage imageFromLayer:trackGradientLayer] resizableImageWithCapInsets:UIEdgeInsetsZero];
    [self setMinimumTrackImage:trackImage forState:UIControlStateNormal];
    [self setMaximumTrackImage:trackImage forState:UIControlStateNormal];
}

Where colors is array of CGColor.

I have also created a category on UIImage which creates image from layer as you need an UIImage for setting gradient on slider.

+ (UIImage *)imageFromLayer:(CALayer *)layer
{
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, layer.opaque, 0.0);

    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return outputImage;
}
like image 6
Palli Avatar answered Oct 08 '22 03:10

Palli


For Swift 3 and to prevent the slider from scaling the Min image, apply this when setting the its image. Recalculating the slider's left side is not necessary. Only recalc if you can changing the color of the gradient. The Max image does not seem to scale, but you should probably apply the same setting for consistency. There is a slight difference on the Max image when not applying its insets.

slider.setMinimumTrackImage(image?.resizableImage(withCapInsets:.zero), for: .normal)

For some reason it only works properly when resizableImage(withCapInsets:.zero) is all done at the same time. Running that part separate does not allow the image to work and gets scaled.

Here is the entire routine in Swift 3:

func setSlider(slider:UISlider) {
    let tgl = CAGradientLayer()
    let frame = CGRect(x: 0.0, y: 0.0, width: slider.bounds.width, height: 5.0 )
    tgl.frame = frame
    tgl.colors = [ UIColor.yellow.cgColor,UIColor.black.cgColor]
    tgl.endPoint = CGPoint(x: 1.0, y:  1.0)
    tgl.startPoint = CGPoint(x: 0.0, y:  1.0)

    UIGraphicsBeginImageContextWithOptions(tgl.frame.size, false, 0.0)
    tgl.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    slider.setMaximumTrackImage(image?.resizableImage(withCapInsets:.zero),  for: .normal)
    slider.setMinimumTrackImage(image?.resizableImage(withCapInsets:.zero),  for: .normal)
}
like image 3
Goodtime Avatar answered Oct 08 '22 03:10

Goodtime