我试图创建一个表格视图(自定义类而不是UITableView),其结果具有渐变效果,如下面的示例图片所示:
我尝试了什么:
FAILED ATEMPT:
FAILED ATEMPT:
最后要尝试的事情:
假设您有两种颜色,color1和color2。通过混合这些颜色可以产生梯度。在上面的图片中color1 =紫色,color2 =橙色。通过根据结果数量划分渐变来创建渐变效果很容易,然后找到每个部分的平均颜色,并将其用作每个相应结果的文本颜色。
例如:
5个结果= 5个分区。
结果并不详细,因为每个文字都是纯色,但是当文字较小时同样令人印象深刻:
问题是,对于这两种颜色:
紫色:128.0,0.0,255.0
橙色:255.0,128.0,0.0
如何将其划分为5个部分并找到每个部分的平均值?
我可以使用pixelmator中的吸管工具来做到这一点,但只有当我知道固定数量的结果时,才能使用6个结果。
我不能用数学来处理它,我不知道从哪里开始。
有什么想法吗?
答案 0 :(得分: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
,但是将上面的Swift代码转换为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
测试结果
它也适用于任意数量的部分和不同的颜色!
答案 1 :(得分:1)
所以你想要这个:
有几种方法可以实现这一点。这是一种像素完美的方式(它通过标签绘制渐变而不是使每个标签成为纯色)。
创建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:
覆盖中):
调用super
只是正常绘制文字。
设置图形上下文混合模式kCGBlendModeSourceIn
。此混合模式告诉Core Graphics仅绘制已绘制上下文的位置,并覆盖在那里绘制的内容。因此,Core Graphics将super
绘制的文本视为掩码。
使用 coverage 视图顶部的起点和 coverage 视图底部的终点绘制渐变, not 位于当前标签的顶部和底部。因此,渐变跨越整个覆盖范围视图,但被遮盖以仅显示在步骤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
这是我的故事板中的布局:
对于所有五个GradientLabel
个实例,我将startColor
设置为紫色,将endColor
设置为橙色,然后将gradientCoverageView
插座连接到封闭堆栈视图。
答案 2 :(得分:0)
嗯,这里是如何在最后做纯色浊位:
如果您有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));
希望这有帮助。
答案 3 :(得分:0)
对于Xamarin iOS C#
public static List<UIColor> DividedColors(UIColor firstColor, UIColor secondColor, int sections)
{
nfloat firstRed = 0;
nfloat firstGreen = 0;
nfloat firstBlue = 0;
nfloat firstAlpha = 0;
firstColor.GetRGBA(out firstRed, out firstGreen, out firstBlue, out firstAlpha);
nfloat secondRed = 0;
nfloat secondGreen = 0;
nfloat secondBlue = 0;
nfloat secondAlpha = 0;
secondColor.GetRGBA(out secondRed, out secondGreen, out secondBlue, out secondAlpha);
nfloat Mix(nfloat first, nfloat second, nfloat ratio)
{
return first + ratio * (second - first);
}
List<UIColor> colors = new List<UIColor>();
var ratioPerSection = 1.0f / sections;
for (int i = 0; i < sections; i++)
{
var newRed = Mix(firstRed, secondRed, ratioPerSection * i);
var newGreen = Mix(firstGreen, secondGreen, ratioPerSection * i);
var newBlue = Mix(firstBlue, secondBlue, ratioPerSection * i);
var newAlpha = Mix(firstAlpha, secondAlpha, ratioPerSection * i);
var newColor = new UIColor(newRed, newGreen, newBlue, newAlpha);
colors.Add(newColor);
}
return colors;
}