38 votes

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

J'ai actuellement deux UIViews : une sur fond rouge et l'autre sur fond bleu. La vue bleue est une sous-vue de la vue rouge. J'aimerais pouvoir "découper" des rectangles sur la vue bleue pour que la vue rouge soit visible. Comment s'y prendre ?

75voto

Jacques Points 4622

Vous devez remplacer la fonction drawRect méthode. Ainsi, par exemple, vous pouvez créer un HoleyView qui dérive de UIView (vous pouvez le faire en ajoutant un nouveau fichier à votre projet, en sélectionnant Objective-C subclass, et en réglant "Subclass of" sur UIView ). Sur le site HoleyView , drawRect ressemblerait à quelque chose comme ça :

- (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 Interface builder, assurez-vous de changer la classe de la vue trouée en HoleyView . Vous pouvez le faire en sélectionnant la vue dans Interface Builder et en sélectionnant le volet "Identity" dans l'inspecteur (celui qui se trouve à l'extrême droite de l'icône "i").

Vous devez également définir la vue supérieure pour qu'elle soit non opaque, soit avec le code suivant, soit en décochant l'option Opaque dans les propriétés de la vue dans Interface Builder (vous la trouverez dans la section View des attributs de la vue) et définissez l'opacité de sa couleur d'arrière-plan à 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 à l'adresse suivante ici .

Pour dessiner une ellipse au lieu du rectangle, votre drawRect ressemblerait à quelque chose comme ça :

- (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 );
    }
}

35voto

rage Points 1149

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

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 coup d'œil à la page d'accueil. Référence au CGContext .

17voto

valvoline Points 2358

Pour dessiner une ellipse, au lieu d'un rectangle, il suffit de régler 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 );
}

1voto

Adam Eberbach Points 9587

Ce sont peut-être des moyens stupides, mais je ne le ferais pas de la manière que vous décrivez, mais je le ferais ressembler à ce que vous voulez.

(La réponse de Jacques vient de s'afficher - elle me semble bonne)

Approche 1 : Dans le contrôleur de vue, construisez une liste de rectangles qui se répartissent autour du "trou" exposé. Au fur et à mesure que le nombre de trous augmente, le nombre de rectangles à carreler augmente également.

Approche 2 : Inversez votre façon de penser. La vue bleue doit se trouver à l'arrière et des sections de la vue rouge doivent être placées au-dessus. Vous voyez toujours une vue rouge dont tous les trous sont masqués par la vue bleue, mais ce que vous faites réellement, c'est copier des régions de la vue que vous voulez exposer et les placer au-dessus du masque à mesure que vous faites chaque trou. Si vous disposez d'un effet simulant la profondeur, vous pouvez l'ajouter à chaque trou.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X