2015-01-15 89 views
2

我正在研究一个设计应用程序,该应用程序有一个用于通过RGB的三个滑块选择颜色的部分。 正如我们在xcode中看到的那样,我们希望通过RGB值选择一种颜色,滑块色调颜色是一种渐变颜色,在我们更改滑块时会发生变化。我想在我的应用程序中使用它。但我不知道如何做到这一点?如何在XCode 6中为UISlider添加渐变色彩颜色?

我在博客中发现了这段代码。但没有为我工作。

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

} 

我将不胜感激任何帮助。谢谢。

回答

2

这是一个非常有效的方法,我发现后,大量的网页搜索。所以最好在这里分享它作为一个完整的答案。以下代码是Swift Class您可以使用它来创建和使用渐变,如UIViewUIImage

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 
    } 
} 
+0

您能否提供此代码的使用说明? – 2017-12-12 11:56:39

4

以下是可能的解决方案:

用法:

//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; 
} 
2

尽管它没有给我想要的结果,但对于那些想要尝试它的人来说,这是一个令人满意的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) 

} 
+0

但我有一个快速的版本给出了预期的效果。如果你可能想使用它,我会在这里分享它 – 2016-03-27 12:52:47

+0

@HosseinMaktoobian它的工作原理...只是不是我想要的。当您滑动时,图像会缩放,例如,如果我只有红色和蓝色,我希望红色显示高达幻灯片的50%,其他50%显示蓝色。但是,这是红色和蓝色总是可见的只是缩小到适合内容大小。 – DogCoffee 2016-03-27 13:14:26

+0

看看我的答案。你应该为你的问题操纵位置。并且当Th视图变化时,您必须刷新渐变 – 2016-03-27 13:19:28

3

对于Swift 3,为了防止滑块缩放Min图像,请在设置图像时应用此选项。重新计算滑块的左侧不是必需的。只有在可以更改渐变的颜色时才能重新计算。最大图像似乎没有缩放,但您应该应用相同的设置来保持一致性。不使用插图时,最大图像略有差异。

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

由于某些原因,它只有在resizableImage(withCapInsets:.zero)全部同时完成时才能正常工作。单独运行该部分不允许图像工作并缩放。

这里是斯威夫特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) 
}