【发布时间】:2011-11-17 09:12:05
【问题描述】:
对于我的应用程序,我使用的是 TableView 并使用自定义的 UITableViewCells。
我通过界面生成器自定义了我的单元格,而不是通过编程方式。有没有办法让我的自定义单元格的背景颜色在界面生成器中成为渐变?
谢谢。
【问题讨论】:
标签: ios uitableview interface-builder
对于我的应用程序,我使用的是 TableView 并使用自定义的 UITableViewCells。
我通过界面生成器自定义了我的单元格,而不是通过编程方式。有没有办法让我的自定义单元格的背景颜色在界面生成器中成为渐变?
谢谢。
【问题讨论】:
标签: ios uitableview interface-builder
这适用于 Swift 3.0:(已针对 Swift 4.0 更新)
@IBDesignable
final class GradientView: UIView {
@IBInspectable var startColor: UIColor = UIColor.clear
@IBInspectable var endColor: UIColor = UIColor.clear
override func draw(_ rect: CGRect) {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = CGRect(x: CGFloat(0),
y: CGFloat(0),
width: superview!.frame.size.width,
height: superview!.frame.size.height)
gradient.colors = [startColor.cgColor, endColor.cgColor]
gradient.zPosition = -1
layer.addSublayer(gradient)
}
}
【讨论】:
gradient.zposition = -1 来解决这个问题。
gradient.frame = bounds 给了我预期的行为。
要绘制渐变,您必须以编程方式继承并覆盖 drawRect:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents
(colorSpace,
(const CGFloat[8]){1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f},
(const CGFloat[2]){0.0f,1.0f},
2);
CGContextDrawLinearGradient(context,
gradient,
CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMinY(self.bounds)),
CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMaxY(self.bounds)),
0);
CGColorSpaceRelease(colorSpace);
CGContextRestoreGState(context);
}
将单元格保留在界面构建器中的最简单方法可能是将 UIView 子类化以使其在其 drawRect 中绘制渐变并将其放置在其他子视图后面的单元格中:
GradientView *gradientView = [[GradientView alloc] init];
gradientView.frame = cell.bounds;
[cell addSubview:gradientView];
[cell sendSubviewToBack:gradientView];
但是,最好的方法可能是不为此使用界面构建器并创建 UITableViewCell 的子类。对于高级定制,根据我的经验,界面构建器往往只会让事情变得更复杂。不过这取决于个人喜好。
【讨论】:
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = yourView.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor blackColor] CGColor], (id) [[UIColor whiteColor] CGColor], nil];
[yourView.layer insertSublayer:gradient atIndex:0];
【讨论】:
是的,这是可能的:使用 1 X 高度像素以渐变方式制作图像。 将此设置为单元格的 backgroundColor。
cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"gradImage.png"]];
**您可以使用代码设置渐变颜色,但需要时间。如果您填写得更好,请搜索。
【讨论】:
@2x 提供两个图像的模式,您就不会看到任何模糊。
answer by etayluz 工作正常,但我添加了一些更改:
在每次绘制时删除渐变层,这样它就不会在需要重绘时继续绘制和添加新层(例如通过在旋转时调用.setNeedsDisplay())。
@IBDesignable final class MFGradientView: UIView {
@IBInspectable var startColor: UIColor = UIColor.clear
@IBInspectable var endColor: UIColor = UIColor.clear
override func draw(_ rect: CGRect) {
layer.sublayers?.first?.removeFromSuperlayer()
let gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = CGRect(origin: CGPoint.zero, size: self.bounds.size)
gradient.colors = [startColor.cgColor, endColor.cgColor]
layer.insertSublayer(gradient, at: 0)
}
}
【讨论】:
根据 etayluz 的回答,我通过考虑 UIView 的 layerClass 属性稍微更改了代码,因此您不需要单独的图层作为子图层.
我认为它更简洁,而且它也适用于 Interface Builder 中的实时更新。
@IBDesignable final class GradientView: UIView {
@IBInspectable var startColor: UIColor = UIColor.red
@IBInspectable var endColor: UIColor = UIColor.blue
override class var layerClass: AnyClass {
get {
return CAGradientLayer.self
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupGradient()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupGradient()
}
private func setupGradient() {
let gradient = self.layer as! CAGradientLayer
gradient.colors = [startColor.cgColor, endColor.cgColor]
}
}
【讨论】:
使用@IBInspectable 属性创建一个简单的视图类。
...
//
// GradientView.swift
//
// Created by Maksim Vialykh on 23.08.2018.
// Copyright © 2018 Vialyx. All rights reserved.
//
import UIKit
class GradientView: UIView {
@IBInspectable
var startColor: UIColor = .white
@IBInspectable
var endColor: UIColor = .black
private let gradientLayerName = "Gradient"
override func layoutSubviews() {
super.layoutSubviews()
setupGradient()
}
private func setupGradient() {
var gradient: CAGradientLayer? = layer.sublayers?.first { $0.name == gradientLayerName } as? CAGradientLayer
if gradient == nil {
gradient = CAGradientLayer()
gradient?.name = gradientLayerName
layer.addSublayer(gradient!)
}
gradient?.frame = bounds
gradient?.colors = [startColor.cgColor, endColor.cgColor]
gradient?.zPosition = -1
}
}
【讨论】:
我不知道是否有渐变选项,但是您可以将 UIImageView 添加到自定义单元格并添加带有渐变的图像。
【讨论】:
不,你不能。您可以将 UISegmentedControl 与旧 sdk 和 xCode 版本中的一个段一起使用: http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ 但是现在你不能在一个 UISegmentedControl 中创建少于两个段。即使这样,您也无法在不编码的情况下更改按钮的默认颜色。
【讨论】: