2017-09-01 176 views
1

我试图创建一个表视图(定制类没有的UITableView),其中它的结果有一个像下面的示例图像中的渐变效果:如何使用颜色分区创建渐变效果?

enter image description here

我试了一下:

  1. 我成功地设法将正确的渐变作为背景添加到每个表格单元格中,但我需要它是每个标签的文本颜色,而不是每个单元格的背景。 Question。 (I问这一个。)

FAILED ATEMPT:

enter image description here

  • 创建自定义梯度图像和将其添加为colorWithPatternImage:给每个标签,但由于每个单元的梯度是一样的。 Question
  • 失败ATEMPT:

    enter image description here

    最后一件事尝试:

    假设有两种颜色,颜色1和颜色2。通过混合这些颜色可以产生渐变效果。在上图中,color1 =紫色,color2 =橙色。通过根据结果的数量除分节中的梯度,然后找到每个节的平均颜色并将其用作每个对应结果的文本颜色,可以很容易地创建渐变效果。

    例如:

    5个结果= 5个部门。

    • division1 =紫色
    • division2 =更少紫色,橙色的
    • division3 =等于紫色,等于橙
    • division4 =至少紫色,最橙色
    • division5 =橙

    结果并不尽如人意,因为每个文字都是纯色,但在文字较小时同样令人印象深刻:

    enter image description here

    的问题是,对于两种颜色像这样:

    紫色:128.0,0.0,255.0

    橙色:255.0,128.0,0.0

    你怎么把它在5个部分,并找到每个部分的平均值?

    我可以使用像素仪中的吸管工具来做到这一点,但只有当我知道固定数量的结果时,才能使用6个结果。

    我不能用数学来处理它,我不知道从哪里开始。

    任何想法?

    回答

    1

    您可以对颜色的rgb值使用数学运算。

    要获得rgb值,您可以使用getRed:green:blue:alpha方法UIColor。然后,您所要做的就是根据您需要多少部分将颜色进行平均。

    这是一个函数,它应该根据开始和结束颜色以及您需要多少个分区来返回一组颜色。

    解决方案

    func divideColors(firstColor: UIColor, secondColor: UIColor, sections: Int) -> [UIColor] { 
    
        // get rgb values from the colors 
        var firstRed: CGFloat = 0; var firstGreen: CGFloat = 0; var firstBlue: CGFloat = 0; var firstAlpha: CGFloat = 0; 
        firstColor.getRed(&firstRed, green: &firstGreen, blue: &firstBlue, alpha: &firstAlpha) 
        var secondRed: CGFloat = 0; var secondGreen: CGFloat = 0; var secondBlue: CGFloat = 0; var secondAlpha: CGFloat = 0; 
        secondColor.getRed(&secondRed, green: &secondGreen, blue: &secondBlue, alpha: &secondAlpha) 
    
        // function to mix the colors 
        func mix(_ first: CGFloat, _ second: CGFloat, ratio: CGFloat) -> CGFloat { return first + ratio * (second - first) } 
    
        // variable setup 
        var colors = [UIColor]() 
        let ratioPerSection = 1.0/CGFloat(sections) 
    
        // mix the colors for each section 
        for section in 0 ..< sections { 
         let newRed = mix(firstRed, secondRed, ratio: ratioPerSection * CGFloat(section)) 
         let newGreen = mix(firstGreen, secondGreen, ratio: ratioPerSection * CGFloat(section)) 
         let newBlue = mix(firstBlue, secondBlue, ratio: ratioPerSection * CGFloat(section)) 
         let newAlpha = mix(firstAlpha, secondAlpha, ratio: ratioPerSection * CGFloat(section)) 
         let newColor = UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: newAlpha) 
         colors.append(newColor) 
        } 
    
        return colors 
    
    } 
    

    你的问题被标记为Objective-C,但它应该是很容易的雨燕代码转换上面的Objective-C,因为你会使用相同的UIColor API。

    下面是测试上述功能的一些代码(适用于Swift操场)。

    测试代码

    let sections = 5 
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 250, height: 50)) 
    for (index, color) in divideColors(firstColor: UIColor.purple, secondColor: UIColor.orange, sections: sections).enumerated() { 
        let v = UIView(frame: CGRect(x: CGFloat(index) * 250/CGFloat(sections), y: 0, width: 250/CGFloat(sections), height: 50)) 
        v.backgroundColor = color 
        view.addSubview(v) 
    } 
    view.backgroundColor = .white 
    

    测试结果

    An image of the five colors, evenly divided between purple and orange

    它也适用于任何数量的部分和不同颜色的!

    An image of more colors, evenly divided between red and yellow

    +0

    如果只有你可以发布这在Objective-c。 – Vulkan

    +0

    @Vulkan无论使用Swift还是Objective-C,API和逻辑都是一样的。现有的SO答案涵盖了如何做所有这些事情(从'UIColor'获得RGB值,创建和修改数组等等) – nathan

    +0

    你是对的,但我无法读Swift,我读了这些:“firstColor。 getRed(&firstRed,green:&firstGreen,blue:&firstBlue,alpha:&firstAlpha)“,”func mix(_ first:CGFloat,_ second:CGFloat,ratio:CGFloat) - > CGFloat {return first + ratio *(second - first) }”。我无法读取它们,也无法将它们转换为ObjC。 – Vulkan

    0

    嗯,这里是如何做实色mathy位底:

    如果你有N + 1种颜色,0 < = M < = N:

    color.red[m] = (purple.red * (m/n)) + (orange.red * ((n-m)/n); 
    color.green[m] = (purple.green * (m/n)) + (orange.green * ((n-m)/n)); 
    color.blue[m] = (purple.blue * (m/n)) + (orange.blue * ((n-m)/n)); 
    

    希望这有助于。

    1

    所以,你要这样:

    screenshot

    有你可以实现这个几个方面。这是一种像素完美的方式(它通过标签绘制渐变,而不是使每个标签都变为纯色)。

    创建UILabel的子类。在您的子类中,覆盖drawTextInRect:以绘制渐变。

    让我们声明子类是这样的:

    IB_DESIGNABLE 
    @interface GradientLabel: UILabel 
    
    @property (nonatomic, weak) IBOutlet UIView *gradientCoverageView; 
    @property (nonatomic, strong) IBInspectable UIColor *startColor; 
    @property (nonatomic, strong) IBInspectable UIColor *endColor; 
    
    @end 
    

    gradientCoverageView插座连接到覆盖的梯度,所以整个区域,覆盖标签的所有五个景色的视图。这可能是标签的超视图,或者它可能只是一个隐藏的视图,您已经设置为(不可见)填充相同的区域。

    startColor设置为紫色,将endColor设置为橙色。

    我们将在三个步骤绘制渐变填充文本(在我们的drawTextInRect:覆盖):

    1. 呼叫super只绘制文本正常。

    2. 设置图形上下文混合模式kCGBlendModeSourceIn。这种混合模式告诉Core Graphics只绘制上下文已经绘制的地方,并且覆盖那里绘制的任何东西。因此Core Graphics将super绘制的文本作为掩码。

    3. 绘制起点的梯度在覆盖视图的顶部,并在覆盖视图底部终点,在当前标签的顶部和底部。因此,梯度跨越整个覆盖视图,但被屏蔽,只显示了在当前标签的文本在步骤1中

    这里绘制的实现:

    @implementation GradientLabel 
    
    - (void)drawTextInRect:(CGRect)rect { 
        [super drawTextInRect:rect]; 
    
        CGContextRef gc = UIGraphicsGetCurrentContext(); 
        NSArray *colors = @[(__bridge id)self.startColor.CGColor, (__bridge id)self.endColor.CGColor]; 
        CGGradientRef gradient = CGGradientCreateWithColors(CGBitmapContextGetColorSpace(gc), (__bridge CFArrayRef)colors, NULL); 
    
        UIView *coverageView = self.gradientCoverageView ?: self; 
        CGRect coverageRect = [coverageView convertRect:coverageView.bounds toView:self]; 
        CGPoint startPoint = coverageRect.origin; 
        CGPoint endPoint = { coverageRect.origin.x, CGRectGetMaxY(coverageRect) }; 
    
        CGContextSaveGState(gc); { 
         CGContextSetBlendMode(gc, kCGBlendModeSourceIn); 
         CGContextDrawLinearGradient(gc, gradient, startPoint, endPoint, 0); 
        } CGContextRestoreGState(gc); 
    
        CGGradientRelease(gradient); 
    } 
    
    @end 
    

    这里的布局在我的故事板:

    storyboard

    对于所有五个GradientLabel情况下,我设置startColor以PUR ple和endColor橙色和我连接gradientCoverageView出口到封闭的堆栈视图。

    +0

    感谢您提供硬核方法。 :d – Vulkan