Recuperer touch d'un CALayer

NiClouNiClou Membre
novembre 2015 modifié dans API UIKit #1

Bonjour à  tous,


Je m'essaye en ce moment meme à  CoreGraphic et aux CALayers.


 


J'essaie de faire un cercle découpé en x morceau... Disons 10.


Et lorsque j'appuie sur un morceau, celui ci change de couleur.


 


Ce que j'ai fait: Une UIView qui gère des CACircleParts (:CALayers).


Ce CACircleParts contient une propriété index.


 


Le problème c'est que ma collection de CACircleParts ont tous la meme frame que ma vue, ils se superposent mais forment bien le cercle voulu. Et lorsque j'appuie sur un des morceaux, c'est toujours l'index le plus elevé qui le capte.


 


Comment faire pour que ce soit le layer qui contient mon "morceau" qui soit retourné dans la méthode suivante:



- (CACircleParts *)layerForTouch:(UITouch *)touch {

CGPoint location = [touch locationInView:self];

CALayer *hitPresentationLayer = [self.containerLayer hitTest:location];
if (hitPresentationLayer) {
return hitPresentationLayer.modelLayer;
}

return nil;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CACircleParts *hitLayer = [self layerForTouch:touch];

// do layer processing...
}

Actuellement il me retourne toujours le morceau avec l'index le plus elevé.


Réponses

  • J'avais cru comprendre que la différence entre les CALayer et les UIView c'était que les CALayer ne géraient que l'affichage et pas les évents.


     


    Tu pourrais récupérer les coordonnées de ton touch et en déduire la bonne CALayer.


  • NiClouNiClou Membre
    novembre 2015 modifié #3


    J'avais cru comprendre que la différence entre les CALayer et les UIView c'était que les CALayer ne géraient que l'affichage et pas les évents.


     


    Tu pourrais récupérer les coordonnées de ton touch et en déduire la bonne CALayer.




     


    Oui tu as raison c'est pour cela que je compare la valeur du touch sur ma vue par rapport aux sublayers.


    Non, car tous mes CALayers ont la meme frame, celle de ma vue.


     


    Sauf erreur de ma part, il n'est pas possible de faire un CALayer triangle.


  • Tu pourrais le déduire en faisant un calcul mathématique !


    (calcul de l'angle avec arctan, etc. en tenant compte du signe de origin.x, etc.)


     


    J'imagine que tu as un camembert avec 10 angles égaux.


  • Tout à  fait. 

    Je suis sur une piste qui pourrait être plus simple.

    Voici comment je dessine mes quartiers:



    -(void)drawInContext:(CGContextRef)ctx
    {
    // Create the path
    CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
    CGFloat radius = MIN(center.x, center.y);

    CGContextBeginPath(ctx);
    CGContextMoveToPoint(ctx, center.x, center.y);

    CGPoint p1 = CGPointMake(center.x + radius * cosf(DEGREES_TO_RADIANS(self.startAngle)), center.y + radius * sinf(DEGREES_TO_RADIANS(self.startAngle)));
    CGContextAddLineToPoint(ctx, p1.x, p1.y);

    CGContextAddArc(ctx, center.x, center.y, radius, DEGREES_TO_RADIANS(_startAngle), DEGREES_TO_RADIANS(_startAngle+_angle), NO);

    CGContextClosePath(ctx);

    CGContextSetFillColorWithColor(ctx, self.fillColor.CGColor);
    CGContextSetStrokeColorWithColor(ctx, self.strokeColor.CGColor);
    CGContextSetLineWidth(ctx, 1);

    CGContextDrawPath(ctx, kCGPathFillStroke);

    }

    Ma question: est il possible de garder une reference sur ce path?


  • CéroceCéroce Membre, Modérateur
    novembre 2015 modifié #6

     


    hitTest:




    Returns the farthest descendant of the receiver in the layer hierarchy (including itself) that contains the specified point.





     


    Tu sais maintenant pourquoi ça te renvoie toujours la dernière layer: puisqu'elles se superposent, le hit test les trouve toutes.


     


    Avec cet agencement, je ne vois pas comment régler le problème hormis savoir dans la vue quel morceau de chaque sublayer apparaà®t.


    Ne pourrais-tu pas réagencer les sublayers pour qu'elles ne se superposent pas ?


     


    Sans doute pas. Alors il faut faire un peu de trigo pour savoir quel est l'angle par rapport au centre, ce qui te permettra de déterminer le segment.


  • Tu devrais utiliser un seul layer pour dessiner ton camembert, et faire ensuite un peu de calcul trigo pour déterminer l'arc de cercle touché par l'utilisateur.

Connectez-vous ou Inscrivez-vous pour répondre.