【问题标题】:Is there a way to make gradient background color in the interface builder?有没有办法在界面生成器中制作渐变背景颜色?
【发布时间】:2011-11-17 09:12:05
【问题描述】:

对于我的应用程序,我使用的是 TableView 并使用自定义的 UITableViewCells。

我通过界面生成器自定义了我的单元格,而不是通过编程方式。有没有办法让我的自定义单元格的背景颜色在界面生成器中成为渐变?

谢谢。

【问题讨论】:

    标签: ios uitableview interface-builder


    【解决方案1】:

    这适用于 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 给了我预期的行为。
    • 这是一种在 StoryBoard 中查看外观的方法吗?
    • 这个怎么设置渐变角度?提前谢谢你
    【解决方案2】:

    要绘制渐变,您必须以编程方式继承并覆盖 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 的子类。对于高级定制,根据我的经验,界面构建器往往只会让事情变得更复杂。不过这取决于个人喜好。

    【讨论】:

    • @SerdarDogruyol 对于我提到的第一个解决方案,UIView。第二个,UITableViewCell。我建议阅读 UIView 类参考以获取有关 UIView 子类化和绘图的更多信息:developer.apple.com/library/ios/#documentation/uikit/reference/…
    • 浮点数组的格式是什么?其中有 8 个,我认为这是设置渐变颜色的一些自定义方法,但我无法弄清楚。
    • @TheJeff 8 个浮点数代表两种颜色:红色、绿色、蓝色、阿尔法、红色、绿色、蓝色、阿尔法。
    • 如果不能解决问题对界面构建器的要求,这怎么可能是正确答案?问题是询问如何在界面生成器中执行此操作,而这个答案实际上拒绝解决这个问题。
    • 这个问题已经超过 6 年了,据我所知,在没有自定义类的界面构建器中没有办法做到这一点。我不知道新版本是否支持它。而且我想 OP 可能不会跟踪这个问题以获取最新答案。
    【解决方案3】:
    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];
    

    【讨论】:

      【解决方案4】:

      是的,这是可能的:使用 1 X 高度像素以渐变方式制作图像。 将此设置为单元格的 backgroundColor。

      cell.backgroundColor =  [UIColor colorWithPatternImage:[UIImage imageNamed:@"gradImage.png"]];
      

      **您可以使用代码设置渐变颜色,但需要时间。如果您填写得更好,请搜索。

      【讨论】:

      • 我相信这是最好的答案:“有没有办法......在界面生成器中”,但你应该提供一个关于如何制作渐变的链接。
      • 但请注意,由于视网膜显示器的原因,当图像与设备不可预测的分辨率不完全匹配时,与其他组件相比,图像可能看起来很难看(像素化)。
      • @Aberrant,由于视网膜显示器,分辨率没有什么不可预测的。只要您遵循@2x 提供两个图像的模式,您就不会看到任何模糊。
      • @KirkWoll 抱歉,视网膜显示确实与此无关。我应该说的是“由于不可预测的像素分辨率”。基本上不可能确定您的 100 像素图像是否将显示在 100、200、437 或任何数量的像素上。但实际上,这不是视网膜显示器的特定问题,而是通常在不可预测的分辨率上的屏幕相关图像尺寸。
      【解决方案5】:

      answer by etayluz 工作正常,但我添加了一些更改:

      1. 渐变大小由自己的层边界定义,而不是超级视图。
      2. 在每次绘制时删除渐变层,这样它就不会在需要重绘时继续绘制和添加新层(例如通过在旋转时调用.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)
            }
        } 
        

      【讨论】:

      • 不要抄袭别人的答案。这应该放在评论中。
      • 我无法发表评论。没有足够的声誉。
      • 这是一个非常糟糕的违反规则的借口。赚它。
      • 记得将内容模式设置为重绘,这样才能在正确旋转屏幕时工作
      【解决方案6】:

      根据 etayluz 的回答,我通过考虑 UIViewlayerClass 属性稍微更改了代码,因此您不需要单独的图层作为子图层.

      我认为它更简洁,而且它也适用于 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]
          }
      
      }
      

      【讨论】:

      • 如何将它添加到项目中?我已经用您的代码创建了一个 GradientView 类,但是将该文件指定为自定义类(并在 IB 中指定颜色)不会应用渐变;我只看到一个白色背景并且 setupGradient 没有被调用。
      【解决方案7】:

      使用@IBInspectable 属性创建一个简单的视图类。

      1. 一次创建渐变层
      2. 重复使用每个布局子视图的渐变层

      ...

      //
      //  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
          }
      
      }
      

      【讨论】:

        【解决方案8】:

        我不知道是否有渐变选项,但是您可以将 UIImageView 添加到自定义单元格并添加带有渐变的图像。

        【讨论】:

          【解决方案9】:

          不,你不能。您可以将 UISegmentedControl 与旧 sdk 和 xCode 版本中的一个段一起使用: http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ 但是现在你不能在一个 UISegmentedControl 中创建少于两个段。即使这样,您也无法在不编码的情况下更改按钮的默认颜色。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-10
            • 2019-09-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多