2017-09-01 178 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