Как вы можете замаскировать UIImage с помощью UIControl? - PullRequest
0 голосов
/ 19 февраля 2019

Я могу установить свойство маски UIImage для другого UIView, но если я устанавливаю свойство маски UIImage в UISwitch, UIImage и UISwitch не отображаются.

    recordMicSwitch = UISwitch()
    guard let sc = recordMicSwitch else { return }
    sc.frame = CGRect(x: deviceWidth - sc.frame.size.width - rightMargin, y: yPos, width: 0, height: 0)
    sc.onTintColor = UIColor(red: 0, green: 0.717, blue: 1.0, alpha: 1.0)
    view.addSubview(sc)

    let image: UIImage = UIImage(named: "testBGGradient.png")!
    let bgImage = UIImageView(image: image)
    bgImage.frame = CGRect(x:200, y:120, width:bgImage.frame.width/2, height:bgImage.frame.height/2)
    bgImage.mask = recordMicSwitch!
    self.view.addSubview(bgImage) 

1 Ответ

0 голосов
/ 20 февраля 2019

Так что на самом деле это не так просто, как просто замаскировать наше изображение на UISwitch.

Причина, по которой этот простой подход не сработает, заключается в том, как на самом деле работает маскировка.Когда мы маскируем изображение, которое вы предлагаете, мы принимаем форму другого вида и применяем его к нашему изображению.Затем наше изображение фактически добавляется к родителю.В итоге мы получаем изображение, обрезанное по форме нашего переключателя (это изображение не получает ни одного из событий переключателя).

То, что нам на самом деле нужно сделать, немного сложнее.Нам нужно добавить наше изображение к различным частям subview s коммутатора и вместо этого замаскировать их.

Для удобства я создал собственный класс коммутатора, который выполняет тяжелую работу за кулисами.:

class ImageTintSwitch: UISwitch {

    init(tintImage: UIImage) {
        super.init(frame: .zero)

        // Make sure we have subviews & grab the first one
        guard let element = subviews.first else { return }

        // Loop through only the subviews that clipToBounds inside the one we grabbed
        for (index, view) in element.subviews.enumerated() where view.clipsToBounds {

            // Add our image only where we need it
            configure(with: tintImage, on: element, maskedTo: view, atIndex: index)
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func configure(with image: UIImage, on parent: UIView, maskedTo view: UIView, atIndex index: Int) {
        // Make an imageView with our image
        let imageView: UIImageView = {
            let view = UIImageView(image: image)
            view.translatesAutoresizingMaskIntoConstraints = false
            return view
        }()

        // Insert our new imageView only where we need it
        parent.insertSubview(imageView, at: index)

        // Mask our imageView to the views that we found
        imageView.mask = view

        // Constrain our imageView to match the parent view
        NSLayoutConstraint.activate([
            imageView.centerXAnchor.constraint(equalTo: parent.centerXAnchor),
            imageView.centerYAnchor.constraint(equalTo: parent.centerYAnchor),
            imageView.widthAnchor.constraint(equalTo: parent.widthAnchor),
            imageView.heightAnchor.constraint(equalTo: parent.heightAnchor)
            ])
    }
}

Чтобы использовать этот пользовательский переключатель, мы можем просто использовать следующий код:

let customSwitch = ImageTintSwitch(tintImage: UIImage(named: "gradient.jpg") ?? UIImage())

Вот результат:

Switch GIF

...