在 UIImageView 上添加渐变

Add a gradient on UIImageView

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

我想在这个 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.
}
}

我建议在 UIImageView:

之上放置一个带有渐变的 UIView
@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)

Objective-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];

您可以为 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{[=10=].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{[=10=].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。始终像通用函数一样思考,然后您以后可以在其他视图中轻松更改渐变颜色。

在Swift 5.1中,我创建了一个自定义的class,它继承自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({ [=10=].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
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)

这些解决方案对我来说效果不佳。这个答案的灵感来自 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)

如我所愿。最重要的一点是给渐变图层添加内容

这应该是正确答案

扩展 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)
}

}