23

我的 iPad 应用程序中有一个图像,我基本上想在它上面放置一个滤色器。为此,我有一个彩色 UIView,它被遮盖到我放在图像上的特定形状。由于调整 alpha 并没有给我想要的效果,我想改用混合模式。

据我所知,您只能在图像上使用混合模式,而不能在普通视图上使用。视图的颜色是动态的,所以我不能只使用图片。

我还尝试将视图光栅化为图像,但这一切都变得像素化和奇怪或其他什么,但也许我做错了什么。

所以,基本问题是:是否可以将混合模式应用于视图?还是我应该采取完全不同的方法来达到相同的目标?

4

2 回答 2

14

查看 CALayer 的 compositingFilter 的文档:https ://developer.apple.com/documentation/quartzcore/calayer/1410748-compositingfilter

在您的颜色叠加视图上,您​​可以设置view.layer.compositingFilterCICategoryCompositeOperation以实现与其背后的内容混合。这是一些示例游乐场代码,其中应用了多重混合模式来对其进行测试(UIImage(named: "")用您自己的图像替换以进行测试)

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {

        let mainView = UIView()
        self.view = mainView

        let image = UIImageView()
        image.translatesAutoresizingMaskIntoConstraints = false;
        image.image = UIImage(named: "maxresdefault.jpg")
        mainView.addSubview(image)

        let overlay = UIView()
        overlay.translatesAutoresizingMaskIntoConstraints = false;
        overlay.backgroundColor = .red
        overlay.layer.compositingFilter = "multiplyBlendMode"
        mainView.addSubview(overlay)

        mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))
        mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))

        mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay]))
        mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay]))
    }
}

PlaygroundPage.current.liveView = MyViewController()
于 2017-10-10T21:44:19.100 回答
7

iOS 13、斯威夫特 5

关键是compositingFilter在适当的 CALayer 上设置属性(顶部的那个 - 它与它后面的任何东西混合)。UIViews 或 CALayers 之间的颜色混合工作。你可以在这里找到混合模式CICategoryCompositeOperation。要使用过滤器,只需去掉CI& 小写名称的第一个字母(例如CIDivideBlendMode变成divideBlendMode)。这是一些游乐场代码来说明:

import UIKit
import PlaygroundSupport

let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 900))
PlaygroundPage.current.liveView = view


let heightIncrement = view.frame.height / 13
let widthIncrement = view.frame.width / 7


// TOP EXAMPLE (UIViews)

let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2,
                                          y: heightIncrement,
                                          width: widthIncrement * 3,
                                          height: heightIncrement * 5))
backgroundView.backgroundColor = .black
view.addSubview(backgroundView)

let overlayView1 = UIView(frame: CGRect(x: widthIncrement,
                                        y: heightIncrement * 2,
                                        width: widthIncrement * 5,
                                        height: heightIncrement))
overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
overlayView1.layer.compositingFilter = "darkenBlendMode"
view.addSubview(overlayView1)

let overlayView2 = UIView(frame: CGRect(x: widthIncrement,
                                        y: heightIncrement * 4,
                                        width: widthIncrement * 5,
                                        height: heightIncrement))
overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
overlayView2.layer.compositingFilter = "divideBlendMode"
view.addSubview(overlayView2)




// BOTTOM EXAMPLE (CALayers)

let backgroundLayer = CALayer()
backgroundLayer.frame = CGRect(x: widthIncrement * 2,
                               y: heightIncrement * 7,
                               width: widthIncrement * 3,
                               height: heightIncrement * 5)
backgroundLayer.backgroundColor = UIColor.black.cgColor
view.layer.addSublayer(backgroundLayer)

let overlayLayer1 = CALayer()
overlayLayer1.frame = CGRect(x: widthIncrement,
                             y: heightIncrement * 8,
                             width: widthIncrement * 5,
                             height: heightIncrement)
overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
overlayLayer1.compositingFilter = "darkenBlendMode"
view.layer.addSublayer(overlayLayer1)

let overlayLayer2 = CALayer()
overlayLayer2.frame = CGRect(x: widthIncrement,
                             y: heightIncrement * 10,
                             width: widthIncrement * 5,
                             height: heightIncrement)
overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
overlayLayer2.compositingFilter = "divideBlendMode"
view.layer.addSublayer(overlayLayer2)

结果如下所示:

描述

我确认相同的代码适用于 iOS。这是视图控制器代码:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)


        let heightIncrement = view.frame.height / 13
        let widthIncrement = view.frame.width / 7


        // TOP EXAMPLE (UIViews)

        let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2,
                                                  y: heightIncrement,
                                                  width: widthIncrement * 3,
                                                  height: heightIncrement * 5))
        backgroundView.backgroundColor = .black
        view.addSubview(backgroundView)

        let overlayView1 = UIView(frame: CGRect(x: widthIncrement,
                                                y: heightIncrement * 2,
                                                width: widthIncrement * 5,
                                                height: heightIncrement))
        overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
        overlayView1.layer.compositingFilter = "darkenBlendMode"
        view.addSubview(overlayView1)

        let overlayView2 = UIView(frame: CGRect(x: widthIncrement,
                                                y: heightIncrement * 4,
                                                width: widthIncrement * 5,
                                                height: heightIncrement))
        overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
        overlayView2.layer.compositingFilter = "divideBlendMode"
        view.addSubview(overlayView2)




        // BOTTOM EXAMPLE (CALayers)

        let backgroundLayer = CALayer()
        backgroundLayer.frame = CGRect(x: widthIncrement * 2,
                                       y: heightIncrement * 7,
                                       width: widthIncrement * 3,
                                       height: heightIncrement * 5)
        backgroundLayer.backgroundColor = UIColor.black.cgColor
        view.layer.addSublayer(backgroundLayer)

        let overlayLayer1 = CALayer()
        overlayLayer1.frame = CGRect(x: widthIncrement,
                                     y: heightIncrement * 8,
                                     width: widthIncrement * 5,
                                     height: heightIncrement)
        overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
        overlayLayer1.compositingFilter = "darkenBlendMode"
        view.layer.addSublayer(overlayLayer1)

        let overlayLayer2 = CALayer()
        overlayLayer2.frame = CGRect(x: widthIncrement,
                                     y: heightIncrement * 10,
                                     width: widthIncrement * 5,
                                     height: heightIncrement)
        overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
        overlayLayer2.compositingFilter = "divideBlendMode"
        view.layer.addSublayer(overlayLayer2)
    }
}

这是模拟器中的结果:

描述

于 2020-04-30T17:16:58.353 回答