Dessiner dans une UIScrollView

Bonjour à  tous,



Je viens vous voir afin de vous demander quelques informations que je n'ai pas vraiment trouvé sur le forum ou ailleurs. En ce moment je développe une application permettant de récupérer les notes jouées par un instrument électronique au format MIDI.



Une fois les notes récupérées et enregistrées dans un tableau d'objets, je désire les afficher à  l'écran. Pour cela j'utilise une classe dérivée de UIView où je dessine d'abord une grille (genre de partition) puis je dessine les notes (simplement des rectangles).



Pour dessiner j'utilise la méthode -(void)drawRect:(CGRect)rect



Voici une partie de mon code :


<br />
- (void)drawRect:(CGRect)rect {<br />
  <br />
	CGContextRef ctx = UIGraphicsGetCurrentContext();<br />
  <br />
	//couleur blanche pour le fond<br />
	CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);<br />
	CGContextFillRect(ctx, self.bounds);<br />
  <br />
	//couleur noire pour les traits de la grille<br />
	CGContextSetRGBStrokeColor(ctx, 0.0, 0.0, 0.0, 1.0);<br />
	CGContextSetLineWidth(ctx, 1);<br />
  <br />
	int nbColonne = 35;<br />
	int nbLigne = 12;<br />
	float espaceColonne = rect.size.width/nbColonne;<br />
	float espaceLigne = rect.size.height/nbLigne;<br />
  <br />
	int width = [self getDrawWithFromCanal:channel];<br />
  <br />
	if(width == 0){<br />
		width = self.frame.size.width;<br />
	}<br />
  <br />
	self.maxWidth = width;<br />
  <br />
	// construction des colonnes<br />
	for (float i = 0; i &lt; width; i+=espaceColonne) {<br />
		float inter = espaceColonne*i;<br />
		CGContextMoveToPoint(ctx, i, 0);<br />
		CGContextAddLineToPoint(ctx, i, self.bounds.size.height);<br />
	}<br />
  <br />
	// construction des lignes<br />
	for (int i = 0; i &lt; nbLigne; i++) {<br />
		float inter = espaceLigne*i;<br />
		CGContextMoveToPoint(ctx, 0, inter);<br />
		CGContextAddLineToPoint(ctx, width, inter);<br />
	}<br />
  <br />
	// traçage des lignes et colonnes<br />
	CGContextStrokePath(ctx);<br />
	[super drawRect:rect];<br />
  <br />
  <br />
	int j =0;<br />
  <br />
	for(int i = 0; i&lt; [arrayOfData count]; i++)<br />
	{<br />
	  <br />
		MidiNote *midiNote = [[MidiNote alloc] init];<br />
		midiNote = [arrayOfData objectAtIndex:i];<br />
		int indexNote = [midiNote valMidiNote]%12;<br />
		int canal = [midiNote canalMidiNote];<br />
	  <br />
		if(canal == channel){<br />
		  <br />
			// coordonnées des notes<br />
			int x = espaceColonne*j;<br />
			int y = espaceLigne*(indexNote);<br />
			int xf = x+espaceColonne*1;<br />
			float yf = y+espaceLigne*1;<br />
		  <br />
			int val = ([[midiNote velocityMidiNote] intValue] - 1)*2;<br />
		  <br />
			//couleur des notes en fonction de la force de frappe (vélocité)<br />
			 CGContextSetRGBStrokeColor(ctx, 0.0, (float)val/255, 0.0, 1.0);<br />
		  <br />
			// construction de la note<br />
			for(int i = x; i &lt;= xf; i++)<br />
			{<br />
				CGContextMoveToPoint(ctx, i, y);<br />
				CGContextAddLineToPoint(ctx, i, yf);<br />
			}<br />
			j++;<br />
		  <br />
			// traçage des notes<br />
			CGContextStrokePath(ctx);<br />
		  <br />
			[super drawRect:rect];<br />
		}<br />
	}<br />
}<br />




Mon problème c'est que je dessine les notes au fur et à  mesure de ce que je lit dans le tableau de note. Ceci induit donc que la taille de la frame est dépassée. J'ai donc inclut cette classe dans une UIScrollView afin d'obtenir une barre de défilement horizontale pour voir toutes les notes.



Le souci est que je doit définir la taille de cette UIScrollView, pour cela j'utilise la méthode contentsize(). Je ne sais pas quelle taille la frame va avoir puisque le nombre de note n'est pas fixe.

alors comment faire en sorte que l'UIScrollView prenne automatiquement la taille de la frame ?



Voici un screen afin que vous puissiez visualiser ce que j'ai déjà  fait.


Réponses

  • CéroceCéroce Membre, Modérateur
    mars 2013 modifié #2
    Bon déjà , dessiner comme tu le fais dans -drawRect: est une mauvaise idée. En effet, dessiner est lourd pour le terminal, et Apple conseille plutôt de multiplier les vues. En effet, une UIView possède une CALayer qui conserve l'image; j'ai déjà  expliqué 20 fois, je ne vais y revenir.



    Ensuite, au niveau du code, c'est simple il faut:

    1) fixer midiView.frame avec la nouvelle largeur

    2) fixer scrollView.contentSize avec la nouvelle largeur.



    Toute la question est: "Qui calcule la nouvelle largeur". Tu es parti du principe que c'était la vue. Je trouve que c'est pas terrible comme solution. Comme c'est le contrôleur qui a accès à  la scrollView et à  la midiView, alors c'est lui qui va appeler les méthodes ci-dessus., et c'est donc lui qui a besoin de connaà®tre la largeur.

    À partir de là , tu peux déplacer le calcul de largeur dans le contrôleur, ou encore mieux, dans un objet MidiViewLayout qui calcule les positions de tout les éléments et qu'on peut partager entre le contrôleur et la MidiView.
Connectez-vous ou Inscrivez-vous pour répondre.