web-dev-qa-db-fra.com

iPhone - Dessinez un rectangle transparent sur UIView pour révéler la vue en dessous

J'ai actuellement deux UIViews: l'un d'un fond rouge et l'autre bleu. La vue bleue est une sous-vue de la vue rouge. Ce que je voudrais faire, c'est pouvoir "découper" des rectangles sur la vue bleue pour que la vue rouge soit visible. Comment procédez-vous?

38
Dave

Vous devez remplacer la méthode drawRect de la vue de dessus. Ainsi, par exemple, vous pouvez créer une classe HoleyView qui dérive de UIView (vous pouvez le faire en ajoutant un nouveau fichier à votre projet, en sélectionnant la sous-classe Objective-C et en définissant "Sous-classe de "à UIView). Dans HoleyView, drawRect ressemblerait à quelque chose comme ceci:

- (void)drawRect:(CGRect)rect {
    // Start by filling the area with the blue color
    [[UIColor blueColor] setFill];
    UIRectFill( rect );

    // Assume that there's an ivar somewhere called holeRect of type CGRect
    // We could just fill holeRect, but it's more efficient to only fill the
    // area we're being asked to draw.
    CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );

    [[UIColor clearColor] setFill];
    UIRectFill( holeRectIntersection );
}

Si vous utilisez le générateur d'interface, assurez-vous de changer la classe de la vue trouée en HoleyView. Vous pouvez le faire en sélectionnant dans la vue d'Interface Builder et en sélectionnant le volet "Identité" dans l'inspecteur (c'est celui à l'extrême droite de l'icône "i").

Vous devez également définir la vue de dessus pour qu'elle soit non opaque soit avec l'extrait de code suivant, soit en décochant la case Opaque dans les propriétés de la vue dans Interface Builder (vous la trouverez dans la section Affichage des attributs de la vue) et définissez l'opacité de sa couleur d'arrière-plan sur 0% (la couleur d'arrière-plan est définie dans la même section).

topView.opaque = NO;
topView.backgroundColor = [UIColor clearColor];

Si vous voulez faire des cercles, vous devez utiliser Core Graphics (alias Quartz 2D). Vous voudrez probablement lire le guide de programmation, qui est disponible ici .

Pour dessiner une ellipse au lieu du rectangle, votre drawRect ressemblerait à ceci:

- (void)drawRect:(CGRect)rect {
    // Get the current graphics context
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor( context, [UIColor blueColor].CGColor );
    CGContextFillRect( context, rect );

    if( CGRectIntersectsRect( holeRect, rect ) )
    {
        CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
        CGContextFillEllipseInRect( context, holeRect );
    }
}
75
Jacques

Il y a du vrai dans toutes les autres réponses, mais il est tout à fait possible de dessiner avec une couleur claire , ou pour ainsi dire effacer les couleurs existantes dans n'importe quel chemin, même avec le - [UIBezierPath fill] ou des méthodes de commodité similaires. Tout ce que vous avez à faire est de définir le mode de fusion du contexte sur une valeur appropriée en fonction de l'effet que vous essayez d'obtenir, comme ceci:

CGContextSetBlendMode(context, kCGBlendModeClear);
[[UIColor clearColor] set];
[myArbitraryPolygonPath fill];

Il y a environ deux douzaines d'options différentes parmi lesquelles vous pouvez choisir, jetez un œil à la référence CGContext .

35
rage

pour dessiner une ellipse, au lieu d'un rect, réglez simplement le blendMode sur clear:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor( context, [UIColor blackColor].CGColor );
    CGContextFillRect( context, rect );

    CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );

    CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
    CGContextSetBlendMode(context, kCGBlendModeClear);

    CGContextFillEllipseInRect( context, holeRect );
}
17
valvoline

Ce sont peut-être des manières stupides, mais je ne le ferais pas comme vous le décrivez, mais faites-le ressembler à ce que vous voulez qu'il ressemble.

(La réponse de Jacques vient d'apparaître - me semble bien)

Approche 1: Dans le contrôleur de vue pour construire une liste de rectangles qui se tuile autour du "trou" exposé. Au fur et à mesure que vos trous augmentent en nombre, le nombre de tuiles augmente également.

Approche 2: inversez votre façon de penser. La vue bleue doit être à l'arrière avec des sections de la vue rouge placées au-dessus. Vous voyez toujours une vue rouge avec tous les "trous" masqués par la vue bleue, mais ce que vous faites réellement, c'est de copier les régions de la vue que vous souhaitez exposer et de les placer sur le masque lorsque vous faites chaque trou. Si vous avez un effet simulant la profondeur, vous pouvez l'ajouter au besoin avec chaque trou.

Ni l'un ni l'autre ne nécessite de sous-classement ou drawRect :.

1
Adam Eberbach