Question CoreGraphics - Mélange seulement * partie * d'une vue


Je suis récemment tombé sur cet article génial sur l'amélioration des performances de défilement avec UITableViewCells: http://engineering.twitter.com/2012/02/simple-strategies-for-smooth-animation.html - Bien que de nombreux bons conseils puissent être trouvés dans cet article, il y en a un en particulier qui m'a intrigué:

Les tweets de Twitter pour iPhone 4.0 ont une ombre portée sur un arrière-plan texturé subtil. Cela représente un défi, car le mélange est coûteux. Nous avons résolu ce problème en réduisant la zone que Core Animation doit considérer comme non opaque, en divisant les zones d'ombre de la zone de contenu de la cellule.

En utilisant le simulateur iOS, en cliquant sur Déboguer - Couches mélangées de couleur révélerait quelque chose comme ceci:

TwitterTableViewCell

Les zones marquées en rouge sont mélangées et la zone verte est opaque. Génial. Ce que l’article ne mentionne pas, c’est: comment puis-je l’implémenter? Il me semble qu'un UIView est soit opaque, soit non. Il me semble que le seul moyen d'y parvenir serait d'utiliser des sous-vues, mais l'article stipule explicitement une implémentation naïve:

Au lieu de cela, nos cellules Tweet contiennent une seule vue sans sous-vues; un seul drawRect: dessine tout.

Alors, comment découper ce qui est opaque et qu'est-ce qui ne figure pas dans ma méthode drawRect:?


13
2018-05-11 22:29


origine


Réponses:


Dans l'exemple que vous montrez, je ne crois pas qu'ils montrent un fond à travers la vue. Je pense qu'ils simulent un arrière-plan graphique de base. En d'autres termes, dans chaque cellule, ils dessinent une couleur gris clair pour l'arrière-plan. Ils dessinent ensuite l'ombre (en utilisant la transparence) et finalement, ils dessinent le reste du contenu opaque sur le dessus. Je peux me tromper, mais je ne pense pas que vous puissiez rendre certaines parties de la vue transparentes. Si c’est le cas, je serais très, très intéressé parce que j’utilise des graphismes de base tout le temps, mais j’évite les coins arrondis car mélanger toute la vue ne semble pas en valoir la peine.

Mettre à jour

Après avoir fait plus de recherches et examiné les documents d'Apple, je ne crois pas qu'il soit possible qu'une partie seulement de la vue soit opaque. En outre, après avoir lu l'article de blog de Twitter, je ne pense pas qu'ils disent qu'ils l'ont fait. Notez que quand ils disent:

Au lieu de cela, nos cellules Tweet contiennent une seule vue sans sous-vues; un seul drawRect: dessine tout.

Ils parlaient spécifiquement de UILabel et UIImageView. En d'autres termes, au lieu d'utiliser ces vues, ils dessinent l'image directement à l'aide de Core Graphics. En ce qui concerne les UILabels, j'utilise personnellement Core Text, car il supporte davantage les polices, mais peut aussi utiliser quelque chose de plus simple, comme celui de NSString. drawAtPoint:withFont: méthode. Mais le principal point qu'ils essaient de faire passer est que le contenu de la cellule est un dessin CG.

Ensuite, ils passent à une nouvelle section: Éviter de mélanger. Ici, ils se font un devoir de dire qu'ils évitent de se mélanger en:

diviser les zones d'ombre de la zone de contenu de la cellule.

La seule façon de faire est d'utiliser des vues différentes. Ils peuvent utiliser deux approches, mais notez d'abord que les séparateurs de cellules sont eux-mêmes superposés (fournis par la tableView). La première consiste à utiliser plusieurs vues à l'intérieur de la cellule. La deuxième méthode consiste à superposer / masquer les ombres / vues mélangées derrière / sur les cellules en insérant les vues appropriées dans UIScrollView. Compte tenu de leur déclaration précédente à propos de n'avoir qu'une seule vue / drawRect pour chaque cellule, c'est probablement ce qu'ils font. Chaque méthode aura ses défis, mais personnellement, je pense qu'il serait plus facile de diviser la cellule en 3 vues (shadow, content, shadow). Cela faciliterait grandement la gestion des situations de première / dernière cellule.


3
2018-05-14 15:38



Je devrais deviner quelque chose dans ce sens
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_shadows/dq_shadows.html 

  CGContextRef context = UIGraphicsGetCurrentContext();

UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10.0f];

CGContextSaveGState(context);
CGRect leftRect = CGRectZero;
CGContextClipToRect(context, leftRect );
CGContextSetBlendMode(context, kCGBlendModeNormal);
// draw shadow

//    Call the function CGContextSetShadow, passing the appropriate values.
//    Perform all the drawing to which you want to apply shadows.
CGContextSetShadowWithColor(context, CGSizeMake(1.0f, 1.0f), 10.0f, [UIColor blackColor].CGColor);
CGContextAddPath(context, path.CGPath);
CGContextDrawPath(context, kCGPathStroke);


CGContextRestoreGState(context);

CGContextSaveGState(context);
CGRect middleSection = CGRectZero;
CGContextClipToRect(context, middleSection);
CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
CGContextFillRect(context, self.bounds);
// draw opaque
CGContextSetBlendMode(context, kCGBlendModeCopy); 

CGContextRestoreGState(context);

0
2018-05-14 15:38



Mon avis est le suivant: Ne laissez pas Core Animation dessiner des ombres en utilisant les différentes propriétés du calque. Il suffit de dessiner une image pré-générée des deux côtés, ce qui est en fait une ombre. Facturer la hauteur variable d'une cellule dans un tirage extensible peut faire l'affaire.

MODIFIER: Si l'arrière-plan est simple, une ombre pré-rendue peut être appliquée des deux côtés sans savoir qu'elle affecte l'attrait visuel.

Si cela n'est pas applicable, la tableview doit être réduite pour être de la taille sans l'ombre. Ensuite, l'ombre peut être mélangée sans le faire pour chaque cellule mais juste "au dessus". Il ne fait pas vraiment défiler. Cela ne fonctionnera que si l'ombre n'a pas de "texture", sinon on remarquera qu'elle vient d'être appliquée sur le dessus.


0
2018-05-14 18:52