Aller au contenu

dessiner un layout dans un canvas


8motions

Recommended Posts

Bonsoir,

J'ai une View sur laquelle je voudrais dessiner un layout issu de mes ressources. J'ai donc surchargé la méthode onDraw(Canvas canvas) de ma View mais je ne trouve pas la méthode pour "monter en mémoire" mon layout et le dessiner dans le canvas.

Voici mon code à l'heure actuelle :

public class MyView extends View {
@Override
protected void onDraw(Canvas canvas) {
   	// Inflate and instanciate view
   	LayoutInflater inf = LayoutInflater.from(getContext());
   	View vView = inf.inflate(R.layout.custom_view, null);
   	ImageView iView = (ImageView) vView.findViewById(R.id.custom_image);
   	iView.setImageResources(R.drawable.custom_image);
   	// GetBitmap from View
   	Bitmap mViewBitmap = Bitmap.createBitmap(vView.getWidth(), vView.getHeight(), Bitmap.Config.ARGB_8888);
   	Canvas cView = new Canvas(mViewBitmap);
   	vView.draw(cView);
   	// DrawBitmap in View's Canvas
   	canvas.drawBitmap(mViewBitmap, x, y, null);
}
}

avec custom_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_height="wrap_content"
android:layout_width="wrap_content" android:background="@drawable/custom_bubble">
<ImageView android:scaleType="center" android:layout_width="50dp"
	android:layout_height="50dp" android:id="@+id/custom_image"/>
</LinearLayout>

Le soucis c'est que lors de la création du bitmap, le vView.getWidth() et vView.getHeight() sont égaux à 0, cela provoque une exception lors de sa création.

Je ne comprend pas trop comment marche l'inflation de view. Autant si mon layout était du genre MATCH_PARENT je veux bien qu'il soit perdu, mais la je suis en WRAP_CONTENT, il n'a aucune raison (selon moi) de ne pas connaitre son width et son height...

J'ai essayé d'ajouter sans succès les méthodes assez obscures que sont :

    	vView.forceLayout();
   	vView.setDrawingCacheEnabled(true);
   	vView.buildDrawingCache();
   	vView.requestLayout();

Avez vous des idées?

Merci

Lien vers le commentaire
Partager sur d’autres sites

Salut, je dois avouer que plus je relis ton code, plus j'ai du mal à comprendre ce que t'as voulu faire^^

Si tu veux ajouter un layout dans un autre, pourquoi ne pas faire tout simplement un addView (il faut que ton conteneur soit un viewGroup) ? Tu ne seras donc pas obligé de passer par onDraw.

A quoi correspondent x et y ?

Petite chose hors sujet mais toujours utile : la méthode onDraw est une méthode dite critique, elle utilisée souvent et rapidement par la classe View, il faut éviter de créer trop d'objet à l'intérieur par soucis d'optimisation de mémoire, le garbage collector n'a parfois pas le temps de supprimer tous les objets et tu peux te retrouver avec des OutOfMemory :) Essaye d'en mettre un maximum en attribut de ta classe.

Lien vers le commentaire
Partager sur d’autres sites

Si tu veux ajouter un layout dans un autre, pourquoi ne pas faire tout simplement un addView (il faut que ton conteneur soit un viewGroup) ? Tu ne seras donc pas obligé de passer par onDraw.

Non j'ai bel et bien besoin d'une View, pas d'un ViewGroup. Je dessine d'autres choses "à la mano" dans le canvas de cette View

A quoi correspondent x et y ?

x et y correspondent ici à la position dans ma view principale de mon layout à dessiner

Petite chose hors sujet mais toujours utile : la méthode onDraw est une méthode dite critique, elle utilisée souvent et rapidement par la classe View, il faut éviter de créer trop d'objet à l'intérieur par soucis d'optimisation de mémoire, le garbage collector n'a parfois pas le temps de supprimer tous les objets et tu peux te retrouver avec des OutOfMemory :) Essaye d'en mettre un maximum en attribut de ta classe.

Ce code est un résumé de ce que je veux faire, il y a juste les grandes lignes. Bien entendu dans mon draw je n'ai pas de réelle construction de ce "bitmap", celui ci est créé une fois puis sauvegardé et réutilisé pour chaque draw. Je n'ai pas voulu trop surcharger de code ce post.

De même, mon layout ne contient pas qu'une image, je l'ai simplifié pour l'exemple.

Lien vers le commentaire
Partager sur d’autres sites

  • 3 weeks later...

J'ai le même souci que toi, dans le cadre de mon application je dois dessiner un certain nombre de bulles avec du texte dans mon ImageView. Le souci, c'est que je ne sais pas comment dessiner ce Layout perso (seule solution trouvée) dans ma vue. Tu as réussis à répondre partiellement à ma question mais Maintenant je suis bloqué au même endroit que toi :(

Lien vers le commentaire
Partager sur d’autres sites

Si cela peux t'aider j'ai trouvé un moyen de faire, par contre je ne sais pas si cela est 100% sure de marcher. Cela marche dans mon cas précis mais il y a peut-être des effets de bord...

    	// Default draw
   	LayoutInflater inf = LayoutInflater.from(context);
   	LinearLayout vView = (LinearLayout) inf.inflate(R.layout.overlayitem, null);
       	vView.setBackgroundResource(R.drawable.bubble);

   	ImageView iView = (ImageView) vView.findViewById(R.id.image);
       	iView.setImageDrawable(d);
       	iView.setVisibility(View.VISIBLE);
   	TextView tView = (TextView) vView.findViewById(R.id.title);
       	tView.setText("bla bla");
       	tView.setVisibility(View.VISIBLE);
   	tView = (TextView) vView.findViewById(R.id.description);
       	tView.setText("bla bla");
       	tView.setVisibility(View.VISIBLE);

       // Set max Size    	
   	vView.measure(500, 500);
   	vView.layout(0, 0, vView.getMeasuredWidth(), vView.getMeasuredHeight());
   	vView.forceLayout();
   	vView.setDrawingCacheEnabled(true);
   	vView.buildDrawingCache(true);
   	vView.requestLayout();

   	if ((mViewBitmap = vView.getDrawingCache(true)) == null) {
       	mViewBitmap = Bitmap.createBitmap(vView.getMeasuredWidth(), vView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
       	Canvas cView = new Canvas(mViewBitmap);
       	vView.draw(cView);
   	}

Si tu as des remarques n'hésite pas...

Lien vers le commentaire
Partager sur d’autres sites

Merci pour ton code, je test ça mais je ne vois pas où tu indique où dessiner ton mViewBitmap qui semble être en fait le visuel de ton vView.

C'est bon, j'ai trouvé, c'était indiqué dans ton précédent Post. ça marche très bien ta méthode et je n'ai aucun problème de lenteur en plus. Merci beaucoup :)

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...