web-dev-qa-db-fra.com

Dégradé transparent UIView

Étant donné que UIView sur iOS est arbitraire, existe-t-il un moyen d'utiliser Core Graphics (on pense à CAGradientLayer) pour lui appliquer un dégradé "transparent au premier plan"?

Je ne peux pas utiliser un CAGradientLayer standard car l'arrière-plan est plus complexe qu'un UIColor. Je ne peux pas non plus superposer un fichier PNG car l'arrière-plan changera à mesure que ma sous-vue défilera le long de sa vue de défilement verticale parente (voir l'image).

J'ai une solution de repli non élégante: avoir mon sous-vue uiview clip ses sous-vues et déplacer un dégradé png pré-rendu de l'arrière-plan lors du défilement de la vue par défaut du parent.

transparent uiview gradient problem

34
jpsim

Ce fut une solution facile et embarrassante: appliquez un CAGradientLayer en tant que masque de ma sous-vue.

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = _fileTypeScrollView.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor, (id)[UIColor clearColor].CGColor, nil];
gradientLayer.startPoint = CGPointMake(0.8f, 1.0f);
gradientLayer.endPoint = CGPointMake(1.0f, 1.0f);
_fileTypeScrollView.layer.mask = gradientLayer;

Merci à Cocoanetics pour m'avoir orienté dans la bonne direction!

94
jpsim

C'est comme ça que je vais faire. 

Step 1 Définissez une vue en dégradé personnalisée (Swift 4):

import UIKit

class GradientView: UIView {
    override open class var layerClass: AnyClass {
        return CAGradientLayer.classForCoder()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let gradientLayer = self.layer as! CAGradientLayer
        gradientLayer.colors = [
            UIColor.white.cgColor,
            UIColor.init(white: 1, alpha: 0).cgColor
        ]
        backgroundColor = UIColor.clear
    }
}

Step 2 - Faites glisser une UIView dans votre storyboard et définissez sa classe personnalisée sur GradientView

 enter image description here

A titre d'exemple, voici à quoi ressemble la vue en dégradé ci-dessus: 


https://github.com/yzhong52/GradientViewDemo

4
Yuchen Zhong

Gradient Example

Je viens de rencontrer le même problème et j'ai fini par écrire ma propre classe. Cela peut sembler excessif, mais c’est la seule façon pour moi de faire des dégradés avec transparence. Vous pouvez voir mon exemple de code et de code ici

Cela revient essentiellement à un UIView personnalisé qui crée deux images. L'une est une couleur unie, l'autre est un dégradé utilisé comme masque d'image. À partir de là, j'ai appliqué l'image résultante au fichier uiview.layer.content.

J'espère que ça aide, Joe

2
Joe Andolina

Je déteste le dire, mais je pense que vous êtes dans le pays personnalisé UIView. Je pense que j'essaierais d'implémenter cela dans un UIView personnalisé recouvrant la routine drawRect.

Avec cela, vous pouvez avoir cette vue, la placer au-dessus de votre vue à défilement réelle et avoir votre vue en dégradé (si vous voulez) "transmettre" tous les événements tactiles (c'est-à-dire abandonner le premier répondant).

0
trumpetlicks

J'ai utilisé la réponse acceptée (OP) ci-dessus et j'ai rencontré le même problème que celui noté dans un commentaire soulevé - lorsque la vue défile, tout ce qui a commencé hors écran est maintenant transparent, recouvert par le masque.

La solution consistait à ajouter le calque de dégradé en tant que masque de superview, pas à celui de scroll view. Dans mon cas, j'utilise une vue texte qui est contenue dans une vue appelée contentView.

J'ai ajouté une troisième couleur et utilisé locations au lieu de startPoint et endPoint, de sorte que les éléments ci-dessous la vue texte restent visibles.

let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.contentView!.bounds
gradientLayer.colors = [UIColor.white.cgColor, UIColor.clear.cgColor, UIColor.white.cgColor]

// choose position for gradient, aligned to bottom of text view
let bottomOffset = (self.textView!.frame.size.height + self.textView!.frame.Origin.y + 5)/self.contentView!.bounds.size.height
let topOffset = bottomOffset - 0.1
let bottomCoordinate = NSNumber(value: Double(bottomOffset))
let topCoordinate = NSNumber(value: Double(topOffset))
gradientLayer.locations = [topCoordinate, bottomCoordinate, bottomCoordinate]

self.contentView!.layer.mask = gradientLayer

Auparavant, le texte qui commençait hors écran était invisible en permanence. Avec mes modifications, le défilement fonctionne comme prévu et le bouton "Fermer" n'est pas couvert par le masque.

 screenshot

0
jab