Как да добавите градиентен нюанс на цвят към UISlider в XCode 6?

Работя върху дизайнерско приложение, което има раздел за избор на цветове чрез три плъзгача за RGB. Както можем да видим в xcode, където искаме да изберем цвят чрез RGB стойности, цветът на нюанса на плъзгача е градиентен цвят, който се променя, когато променим плъзгачите. Искам да използвам това в моето приложение. но нямам идея как да направя това?

Намерих този код в блог. но не работи за мен.

- (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];

}

Ще се радвам на всяка помощ. Благодаря.


person hmak.me    schedule 15.01.2015    source източник


Отговори (4)


Въпреки че не ми даде желаните резултати, ето една лоша и мръсна Swift версия на отговора по-горе за тези, които искат да го изпробват.

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)

}

АКТУАЛИЗАЦИЯ за 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)
    }
}
person DogCoffee    schedule 27.03.2016
comment
Но имам бърза версия, която дава желаните резултати. В случай, че може да искате да го използвате, ще го споделя тук - person hmak.me; 27.03.2016
comment
@HosseinMaktoobian работи ... просто не както исках. Изображенията се мащабират, когато плъзгате, така че например, ако имах само червено и синьо, бих искал червеното да показва до 50% от слайда, а останалите 50% да показват синьото. Но това беше червеното и синьото, които винаги се виждат, просто намалени, за да отговарят на размера на съдържанието. - person DogCoffee; 27.03.2016
comment
Разгледайте моя отговор. Трябва да манипулирате местоположения за вашия проблем. И вие трябва да опреснявате градиента всеки път, когато изгледът се промени - person hmak.me; 27.03.2016
comment
това трябва да е приетото решение! благодаря @DogCoffee - person AouledIssa; 17.06.2018
comment
добавен е градиент, но контролът се разваля - няма ограничения на линията, усилване на линията y отместване и т.н - person Vyachaslav Gerchicov; 18.04.2019
comment
Това е толкова близо, освен че image.resizableImage(withCapInsets: UIEdgeInsets.zero) връща UIImage, но това не се присвоява на променлива. ако присвоите резултата от това извикване на променлива и след това го предадете на setMinTrackImage, работи чудесно - person user1366911; 13.08.2019

Ето възможно решение:

Употреба:

//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];

Внедряване:

Създайте категория на 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];
}

Където colors е масив от CGColor.

Също така създадох категория на UIImage, която създава изображение от слой, тъй като имате нужда от UIImage за задаване на градиент на плъзгача.

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

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

    UIGraphicsEndImageContext();

    return outputImage;
}
person Palli    schedule 13.04.2015
comment
отлично! благодаря, въпреки че за да бъда 100% правилен, бих използвал frame = [self trackRectForBounds:self.bounds]; така че ще работи добре дори с максимални и минимални изображения - person PakitoV; 11.04.2019

За Swift 3 и за да попречите на плъзгача да мащабира минималното изображение, приложете това, когато задавате неговото изображение. Преизчисляването на лявата страна на плъзгача не е необходимо. Преизчислете само ако можете да промените цвета на градиента. Максималното изображение изглежда не се мащабира, но вероятно трябва да приложите същата настройка за последователност. Има малка разлика в изображението Max, когато не се прилагат неговите вмъквания.

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

По някаква причина работи правилно само когато resizableImage(withCapInsets:.zero) е направено едновременно. Изпълнението на тази част отделно не позволява на изображението да работи и се мащабира.

Ето цялата рутина в 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)
}
person Goodtime    schedule 18.11.2016

Това е наистина ефективен подход, който открих след много търсене в мрежата. Така че е по-добре да го споделите тук като пълен отговор. Следният код е Swift Class, който можете да използвате за създаване и използване на градиенти като UIView или UIImage.

import Foundation
import UIKit

class Gradient: UIView{
    // Gradient Color Array
    private var Colors: [UIColor] = []

    // Start And End Points Of Linear Gradient
    private var SP: CGPoint = CGPoint.zeroPoint
    private var EP: CGPoint = CGPoint.zeroPoint

    // Start And End Center Of Radial Gradient
    private var SC: CGPoint = CGPoint.zeroPoint
    private var EC: CGPoint = CGPoint.zeroPoint

    // Start And End Radius Of Radial Gradient
    private var SR: CGFloat = 0.0
    private var ER: CGFloat = 0.0

    // Flag To Specify If The Gradient Is Radial Or Linear
    private var flag: Bool = false

    // Some Overrided Init Methods
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    // Draw Rect Method To Draw The Graphics On The Context
    override func drawRect(rect: CGRect) {
        // Get Context
        let context = UIGraphicsGetCurrentContext()

        // Get Color Space
        let colorSpace = CGColorSpaceCreateDeviceRGB()

        // Create Arrays To Convert The UIColor to CG Color
        var colorComponent: [CGColor] = []
        var colorLocations: [CGFloat] = []
        var i: CGFloat = 0.0

        // Add Colors Into The Color Components And Use An Index Variable For Their Location In The Array [The Location Is From 0.0 To 1.0]
        for color in Colors {
            colorComponent.append(color.CGColor)
            colorLocations.append(i)
            i += CGFloat(1.0) / CGFloat(self.Colors.count - 1)
        }

        // Create The Gradient With The Colors And Locations
        let gradient: CGGradientRef = CGGradientCreateWithColors(colorSpace, colorComponent, colorLocations)

        // Create The Suitable Gradient Based On Desired Type
        if flag {
            CGContextDrawRadialGradient(context, gradient, SC, SR, EC, ER, 0)
        } else {
            CGContextDrawLinearGradient(context, gradient, SP, EP, 0)
        }
    }

    // Get The Input Data For Linear Gradient
    func CreateLinearGradient(startPoint: CGPoint, endPoint: CGPoint, colors: UIColor...) {
        self.Colors = colors
        self.SP = startPoint
        self.EP = endPoint
        self.flag = false
    }

    // Get The Input Data For Radial Gradient
    func CreateRadialGradient(startCenter: CGPoint, startRadius: CGFloat, endCenter: CGPoint, endRadius: CGFloat, colors: UIColor...) {
        self.Colors = colors
        self.SC = startCenter
        self.EC = endCenter
        self.SR = startRadius
        self.ER = endRadius
        self.flag = true
    }

    // Function To Convert Gradient To UIImage And Return It
    func getImage() -> UIImage {
        // Begin Image Context
        UIGraphicsBeginImageContext(self.bounds.size)

        // Draw The Gradient
        self.drawRect(self.frame)

        // Get Image From The Current Context
        let image = UIGraphicsGetImageFromCurrentImageContext()

        // End Image Context
        UIGraphicsEndImageContext()

        // Return The Result Gradient As UIImage
        return image
    }
}
person hmak.me    schedule 27.03.2016
comment
Можете ли да предоставите обяснение за използването на този код? - person Mykyta Savchuk; 12.12.2017