【问题标题】:Add a gradient on UIImageView在 UIImageView 上添加渐变
【发布时间】:2017-03-17 06:59:38
【问题描述】:

我试图在我的UIImageView 上添加一个子层,但它不起作用。

  • 我有一组 10 张图像,命名为 photo0photo9,我显示 它带有5s的计时器。
  • 插座shanghaiImage是我的背景

我想在这个 marty 顶部添加一个渐变,例如:透明(顶部)到黑色(底部)。

感谢您的帮助:)

这是我在 Swift 3 中的代码。

这部分很好:

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var shanghaiImage: UIImageView!

// beginning index
var _curentImageIndex:Int = 0
// number of images
let NUMBER_OF_IMAGES:Int = 10
// creation of the Timer
var _uiTimer:Timer?


override func viewDidLoad() {
    super.viewDidLoad()
    showPhoto(atIndex: _curentImageIndex)
}

// MARK TIMER ---------

func selectNewTimer(){
    if let existingTimer:Timer = _uiTimer{
        existingTimer.invalidate()
    }
    _uiTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(ViewController.showNextImage), userInfo: nil, repeats: true)
}

这里有问题。我不知道为什么它不起作用。

// MARK PHOTO ---------
func showPhoto(atIndex index:Int){

    let photoName:String =  "photo\(index)"
    shanghaiImage.image =  UIImage(named: photoName)

    let gradient = CAGradientLayer()
    gradient.frame = shanghaiImage.bounds
    let startColor = UIColor(colorLiteralRed: 0, green: 0, blue: 0, alpha: 1)
    let endColor = UIColor.black

    gradient.colors = [startColor, endColor]
    shanghaiImage.layer.insertSublayer(gradient, at: 0)


    _curentImageIndex  =  index
    selectNewTimer()
    }

func showNextImage() {
    var nextPhotoIndex:Int = _curentImageIndex + 1
        if nextPhotoIndex >= NUMBER_OF_IMAGES {
            nextPhotoIndex = 0
        }
    showPhoto(atIndex: nextPhotoIndex)
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

【问题讨论】:

  • “这里有问题” 但是你还没有说是什么问题
  • 哦,写,嗯,事实上我有每 5 秒改变一次的图像;但是我的 UIimageView 上的渐变效果不起作用,我的图像上没有阴影或其他东西:)
  • @Alexandre 你把这张图片保存在 i-Phone 的相册里了吗?

标签: ios uiimageview swift3 uicolor cagradientlayer


【解决方案1】:

这应该是正确的答案

扩展 UIImageView {

func makeGradient() {
    let gradient = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.contents = self.image?.cgImage
    gradient.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
    gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
    gradient.endPoint = CGPoint(x: 0.5, y: 1)
    self.layer.addSublayer(gradient)
}

}

【讨论】:

    【解决方案2】:

    在 Swift 5.1 中,我创建了一个继承自 UIImageView 并支持多种渐变配置的自定义类。

    import UIKit
    import SnapKit
    
    class GradientImageView: UIImageView {
    
        //MARK: - View model
        enum GradientDirection {
            case upDown
            case downUp
            case leftRight
            case rightLeft
            case topLeftBottomRight
            case topRightBottomLeft
            case bottomLeftTopRight
            case bottomRightTopLeft
        }
        
        //MARK: - Properties
        var colors: [UIColor] = [] {
            didSet {
                updateGradient()
            }
        }
        private var cgColors: [CGColor] {
            return colors.map({ $0.cgColor })
        }
        var gradientDirection: GradientDirection = .downUp {
            didSet {
                updateGradient()
            }
        }
        private lazy var gradientLayer: CAGradientLayer = {
            let layer = CAGradientLayer()
        
            layer.shouldRasterize = true
            
            return layer
        }()
        
        
        //MARK: UI
        private lazy var overlayView: UIView = { return UIView() }()
        
        
        //MARK: - Constructor
        init(colors: [UIColor], gradientDirection: GradientDirection) {
            super.init(frame: .zero)
            
            self.colors = colors
            self.gradientDirection = gradientDirection
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
    }
    
    
    //MARK: - Lifecycle methods methods
    extension GradientImageView {
        
        override func didMoveToSuperview() {
            super.didMoveToSuperview()
            
            if superview != nil {
                setupUI()
                updateGradient()
            }
            
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            
            gradientLayer.frame = overlayView.frame
        
        }
        
    }
    
    
    //MARK: - Private methods
    private extension GradientImageView {
        
        func setupUI() {
            addSubview(overlayView)
            //With Snapkit
            overlayView.snp.makeConstraints { (maker) in
                maker.edges.equalToSuperview()
            }
    
            //Without Snapkit
            //overlayView.translatesAutoresizingMaskIntoConstraints = false
            //overlayView.topAnchor.constraint(equalTo: overlayView.superview!.topAnchor).isActive = true
            //overlayView.leftAnchor.constraint(equalTo: overlayView.superview!.leftAnchor).isActive = true
            //overlayView.bottomAnchor.constraint(equalTo: overlayView.superview!.bottomAnchor).isActive = true
            //overlayView.rightAnchor.constraint(equalTo: overlayView.superview!.rightAnchor).isActive = true
    
            overlayView.layer.addSublayer(gradientLayer)
        }
        
        func updateGradient() {
            
            gradientLayer.colors = cgColors
            
            switch gradientDirection {
            case .upDown:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
            case .downUp:
                gradientLayer.startPoint = CGPoint(x: 0.5, y: 1)
                gradientLayer.endPoint = CGPoint(x: 0.5, y: 0)
            case .leftRight:
                gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
                gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
            case .rightLeft:
                gradientLayer.startPoint = CGPoint(x: 1, y: 0.5)
                gradientLayer.endPoint = CGPoint(x: 0, y: 0.5)
            case .topLeftBottomRight:
                gradientLayer.startPoint = CGPoint(x: 0, y: 0)
                gradientLayer.endPoint = CGPoint(x: 1, y: 1)
            case .topRightBottomLeft:
                gradientLayer.startPoint = CGPoint(x: 1, y: 0)
                gradientLayer.endPoint = CGPoint(x: 0, y: 1)
            case .bottomLeftTopRight:
                gradientLayer.startPoint = CGPoint(x: 0, y: 1)
                gradientLayer.endPoint = CGPoint(x: 1, y: 0)
            case .bottomRightTopLeft:
                gradientLayer.startPoint = CGPoint(x: 1, y: 1)
                gradientLayer.endPoint = CGPoint(x: 0, y: 0)
            }
            
        }
        
    }
    

    用法

    let gradientImageView = GradientImageView(colors: [YOUR COLORS], gradientDirection: .upDown)
    gradientImageView.image = //YOUR Image
    

    【讨论】:

    • 如何添加 snapit?
    • github.com/SnapKit/SnapKit 但是我加了没有
    • 我试过这个。它添加了一个渐变,但图像是空白的。
    【解决方案3】:

    这些解决方案不适用于我。这个答案的灵感来自this。 我有 IBOutlet,就像,

    @IBOutlet weak var imageView: UIImageView!
    

    然后我添加了这段代码。

    let gradient = CAGradientLayer()
    gradient.frame = imageView.bounds
    gradient.contents = imageView.image?.cgImage
    gradient.colors = [UIColor.green.cgColor, UIColor.blue.cgColor]
    gradient.startPoint = CGPoint(x: 0, y: 0)
    gradient.endPoint = CGPoint(x: 1, y: 1)
    imageView.layer.addSublayer(gradient)
    

    它按我的意愿工作。最重要的一点是向渐变层添加内容。

    【讨论】:

      【解决方案4】:
      extension UIView {
      
          func addGradient(frame: CGRect) {
              let gradientView = UIView(frame: self.frame)
              let gradientLayer = CAGradientLayer()
              gradientLayer.frame = frame
              gradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
              gradientLayer.locations = [0.0, 1.0]
              gradientView.layer.insertSublayer(gradientLayer, at: 0)
              addSubview(gradientView)
          }
      }
      

      如何使用

      let headerView = UIImageView(frame: viewFrame)
      
      // Setup frame
      let gradientViewFrame = yourGradientFrame;
      headerView.addGradient(frame: gradientViewFrame)
      

      【讨论】:

        【解决方案5】:

        您可以使用 swift 3、swift 4 和 swift 5 的扩展

        为您的 UIImageView 扩展创建一个新文件,如 UIImageView_extension.swift 并设置到此代码中:

        UIImageView 是 UIView 的扩展,因此如果您将 UIImageView 更改为 UIView,那么它会变得更加动态,即所有扩展 UIView 的组件都可以使用它。所以我用 UIView 代替了 UIImageView。

        import UIKit
        
        extension UIView{
           // For insert layer in Foreground
           func addBlackGradientLayerInForeground(frame: CGRect, colors:[UIColor]){
            let gradient = CAGradientLayer()
            gradient.frame = frame
            gradient.colors = colors.map{$0.cgColor}
            self.layer.addSublayer(gradient)
           }
           // For insert layer in background
           func addBlackGradientLayerInBackground(frame: CGRect, colors:[UIColor]){
            let gradient = CAGradientLayer()
            gradient.frame = frame
            gradient.colors = colors.map{$0.cgColor}
            self.layer.insertSublayer(gradient, at: 0)
           }
        }
        

        您可以在 ViewController.swift 中使用它:

        class myViewController: UIViewController{
            @IBOutlet weak var imageView: UIImageView!
        
            override func viewDidLoad() {
            super.viewDidLoad()
        
                imageView.addBlackGradientLayerInBackground(frame: view.bounds, colors:[.clear, .black])
                //Alternative
                //imageView.addBlackGradientLayerInBackground(frame: imageView.frame, colors: [.clear, .black])
            }
        }
        

        这个函数需要一个frame,所以你只需要一个frame from view或者你自己的imageView。总是像泛型函数一样思考,那么你以后可以在其他视图中毫无麻烦地更改渐变颜色。

        【讨论】:

        • 由于这是UIImageView的扩展而不是添加参数框架,您可以使用self.frame属性。代码应该类似于:gradient.frame = self.frame。无论如何,感谢您的解决方案,它确实有效!
        • 嘿,我试过了,效果很好。我唯一面临的问题是渐变没有完全覆盖我的图像,它从右侧留下了一些图像
        • 我同意@eraser2021999,定义框架的行可以是gradient.frame = self.frame,方法应该不接收参数。
        • 嗨,我解决了完全覆盖图像的问题。谢谢你的cmets。 @eraser2021999, Aakash, Iris。
        • @gandhiMena 你是如何解决没有完全覆盖图像的问题的?
        【解决方案6】:

        我建议将带有渐变的UIView 放在UIImageView 之上:

        @IBOutlet weak var shanghaiImage: UIImageView!
        
        let view = UIView(frame: profileImageView.frame)
        
        let gradient = CAGradientLayer()
        
        gradient.frame = view.frame
        
        gradient.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
        
        gradient.locations = [0.0, 1.0]
        
        view.layer.insertSublayer(gradient, at: 0)
        
        shanghaiImage.addSubview(view)
        
        shanghaiImage.bringSubview(toFront: view)
        

        目标-C:

        UIView *view = [[UIView alloc] initWithFrame: profileImageView.frame];
        
        CAGradientLayer *gradient = [[CAGradientLayer alloc] init];
        
        gradient.frame = view.frame;
        
        gradient.colors = @[ (id)[[UIColor clearColor] CGColor], (id)[[UIColor blackColor] CGColor] ];
        
        gradient.locations = @[@0.0, @1.0];
        
        [view.layer insertSublayer: gradient atIndex: 0];
        
        [shanghaiImage addSubview: view];
        
        [shanghaiImage bringSubviewToFront: view];
        

        【讨论】:

        • @DeepakKumar 我更新了我的答案以包含objective-c。我的 Obj-C 有点生锈了,Xcode 现在已经不能使用了,所以它可能有一些错误。
        • @CalebKleveter 我已经使用了这段代码,但现在我想将这张图片保存在我的图库中,我该如何实现?
        • @KhushbuDesai 如果要保存添加了渐变的图像,则涉及更多,因为您必须编辑实际图像本身。我建议四处搜索以尝试找到一些东西。
        • @CalebKleveter 我已经用谷歌搜索了它,但我发现的唯一解决方案是该图像的屏幕截图,它不值得。这就是我在这里问你的原因。
        • @KhushbuDesai 看看这个:hackingwithswift.com/example-code/media/…
        猜你喜欢
        • 1970-01-01
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-04
        • 1970-01-01
        相关资源
        最近更新 更多