在uitableViewCell中的UIView内放置渐变颜色

Posted

技术标签:

【中文标题】在uitableViewCell中的UIView内放置渐变颜色【英文标题】:Place gradient color inside UIView in tableViewCell 【发布时间】:2020-10-29 07:10:41 【问题描述】:

我在堆栈视图中添加了两个视图。我的 tableViewCell 中有那个堆栈视图。现在我的 stackView 被放置在内容视图的中心,具有宽度和高度。我想在我的 stackView 内的视图内应用渐变颜色。

看看下面的视图 在这种情况下,我给视图设置了我不想要的红色和绿色的背景颜色。我想将四种颜色的渐变应用于此视图。 enter image description here

【问题讨论】:

【参考方案1】:

这是我用 Swift 编写的一个简单进度条的代码:

import Foundation
import Cocoa

public class GradientProgressView : NSView

    // MARK: - Fields
    private let bgLayer = CAShapeLayer()
    private var progressLayer = CAShapeLayer()
    private var gradientLayer = CAGradientLayer()
    private var blockLayer = CAShapeLayer()
    private var mValue: CGFloat = 0.0
    
    // MARK: - Properties
    public var colors: [NSColor] = [NSColor.systemGreen, NSColor.systemYellow, NSColor.sytemRed]
    
    public var value: CGFloat
    
        set
        
            self.mValue = newValue
            
            if self.mValue > 1.0
            
                self.mValue = 1.0
            
            if self.mValue < 0.0 || self.mValue.isNaN || self.mValue.isInfinite
            
                self.mValue = 0.0
            
            
            self.progressLayer.strokeEnd = self.mValue
        
        get
        
            return self.mValue
        
    
    
    // MARK: - Overrides
    public override func layout()
    
        super.layout()
        
        self.initialize()
    
    
    // MARK: - Helper
    fileprivate func initialize()
    
        self.wantsLayer = true
        
        self.layer?.masksToBounds = true // Optional
        self.layer?.cornerRadius = self.bounds.height / 2.0 // Optional
        
        self.bgLayer.removeFromSuperlayer()
        self.bgLayer.contentsScale = NSScreen.scale
        self.bgLayer.fillColor = NSColor.separatorColor.cgColor
        self.bgLayer.path = NSBezierPath(rect: self.bounds).cgPath
        self.layer?.addSublayer(self.bgLayer)
        
        self.blockLayer.removeAllAnimations()
        self.blockLayer.removeFromSuperlayer()
        
        let path = NSBezierPath()
        path.move(to: CGPoint(x: self.bounds.height / 2.0, y: self.bounds.height / 2.0))
        path.line(to: CGPoint(x: self.bounds.width - self.bounds.height / 2.0, y: self.bounds.height / 2.0))
        
        self.progressLayer.path = path.cgPath
        self.progressLayer.strokeColor = NSColor.black.cgColor
        self.progressLayer.fillColor = nil
        self.progressLayer.lineWidth = self.bounds.height
        self.progressLayer.lineCap = .round
        self.progressLayer.strokeStart = 0.0
        self.progressLayer.strokeEnd = 0.0
        self.progressLayer.contentsScale = NSScreen.scale
        
        self.gradientLayer.removeAllAnimations()
        self.gradientLayer.removeFromSuperlayer()
        self.gradientLayer.contentsScale = NSScreen.scale
        self.gradientLayer.colors = self.colors.map( $0.cgColor )
        self.gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        self.gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
        self.gradientLayer.mask = self.progressLayer
        self.gradientLayer.frame = self.bounds
        self.gradientLayer.contentsScale = NSScreen.scale
        
        self.layer?.addSublayer(self.gradientLayer)
    

此进度条支持多种颜色。 只需将您的进度条逻辑替换为我在上面发布的逻辑(或添加进度条下方显示的三角形的逻辑)。

预览:

【讨论】:

【参考方案2】:

在 tableViewCell(collectionViewCell) 上创建 GradientLayer

1。在您的 tableViewCell 上创建 CAGradientLayer 实例

class MyCell: UITableViewCell 
    let gradientLayer = CAGradientLayer()

2。将图层框架设置为layoutSublayers(of:) 的视图边界

如果您将图层的框架设置在其他位置,框架会变得很奇怪。

class MyCell: UITableViewCell 
    let gradientLayer = CAGradientLayer()
    
    // Setting it from layoutSubViews also fine.
    override func layoutSublayers(of layer: CALayer) 
        super.layoutSublayers(of: self.layer)
        gradientLayer.frame = yourView.bounds
    

3。在视图上添加 GradientLayer。

这是我用于添加渐变层的 UIView 扩展。

extension UIView 
    func addGradient(with layer: CAGradientLayer, gradientFrame: CGRect? = nil, colorSet: [UIColor],
                     locations: [Double], startEndPoints: (CGPoint, CGPoint)? = nil) 
        layer.frame = gradientFrame ?? self.bounds
        layer.frame.origin = .zero

        let layerColorSet = colorSet.map  $0.cgColor 
        let layerLocations = locations.map  $0 as NSNumber 

        layer.colors = layerColorSet
        layer.locations = layerLocations

        if let startEndPoints = startEndPoints 
            layer.startPoint = startEndPoints.0
            layer.endPoint = startEndPoints.1
        

        self.layer.insertSublayer(layer, above: self.layer)
    

* 选项 1 - 从 layoutSublayers(of:) 添加
class MyCell: UITableViewCell 
    let gradientLayer = CAGradientLayer()
    
    override func layoutSublayers(of layer: CALayer) 
        super.layoutSublayers(of: self.layer)
        gradientLayer.frame = yourView.bounds
        
        let colorSet = [UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1.0),
                        UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0)]
        let location = [0.2, 1.0]
        
        yourView.addGradient(with: gradientLayer, colorSet: colorSet, locations: location)
    

* 选项 2 - 从cellForRowAt 添加

例如,如果我们有 cellForRowAt 并且像这样,

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
  let cell = tableView.dequeueReusableCell(withIdentifier: "yourCellId", for: indexPath) as? MyCell 
      cell.configureCell(content: someItems[indexPath.row])
  
  return UITableViewCell()

现在,我们可以处理来自configureCell(content:) 的gradientLayer。

class MyCell: UITableViewCell 
    let gradientLayer = CAGradientLayer()
    
    func configureCell(content: YourType) 
        let colorSet = [UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1.0),
                        UIColor(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0)]
        let location = [0.2, 1.0]
        yourView.addGradient(with: gradientLayer, colorSet: colorSet, locations: location)
    
    
    override func layoutSublayers(of layer: CALayer) 
        super.layoutSublayers(of: self.layer)
        gradientLayer.frame = yourView.bounds
    

【讨论】:

以上是关于在uitableViewCell中的UIView内放置渐变颜色的主要内容,如果未能解决你的问题,请参考以下文章

在 UIScrollView/UIView 内设置 UITableViewCell 样式

UITableViewCell 位置问题内的 UIView - 已更新

更改 UITableViewCell 内 UIView 的高度(故事板)

UItableviewcell中的pangesture,表格滚动无法快速工作

除非滚动表格,否则 UITableViewCell 内的 UIView 调整大小不显示

根据 `UITableViewCell` 中的 `UILabel` 文本更改 `UIView` 宽度