7
votes

Différence entre dessiner directement sur toile et dessiner sur bitmap, puis toile dans Android ONDRAW ()

J'écris une vue personnalisée qui affiche des signaux. Afin de raccourcir mon temps d'ONDRAW (), je cache tout ce que j'ai dessiné jusqu'à présent dans un bitmap et simplement ajouter à cela dans chaque appel ONDRAW (). En faisant cela, je peux économiser des quantités énormes depuis que je n'ai besoin que de dessiner quelques fixels à la fois au lieu de refaire le tout.

Il y a sur la chose qui me dérange bien - il apparaît comme dessinant directement à la toile fournie fournie Un dessin plus "précis" que de dessiner d'abord sur le bitmap, puis de dessiner le bitmap sur la toile. En regardant la partie inférieure de la photo suivante, vous pouvez voir la différence:

Regardez le Une partie inférieure du signal pour voir la différence - il y a les mêmes appels de traction

J'ai téléchargé un projet de démonstration affichant la divergence à https://github.com/gardarh/androïd-uglybitmapDrawing/ mais le code pertinent est le suivant: xxx

pourquoi Les deux traces ne sont pas identiques et plus importantes, comment puis-je faire ressembler la trace inférieure à la partie supérieure?


4 commentaires

Salut. Merci beaucoup de partager votre code. J'essaie également de créer une application qui affiche des signaux sous forme de graphiques sur l'écran Android et que votre code m'aidait à obtenir des idées. Cependant, je suis aussi débutant à Android et j'ai donc quelques questions de base concernant votre code, alors veuillez supporter avec moi si ces questions sont trop triviales. Première question est, il n'y a aucun code dans la classe de MainActivity qui appelle toutes les fonctions de la classe CachedDrawingjava, mais j'ai pu savoir que la fonction ONDRAW () dans cette autre classe est appelée au moins une fois. Quand et comment cet appel est-il arrivé?


Mon graphique doit être dessiner dans une zone rectangulaire spécifiée dans My Apps Screen, mais les échantillons de codes graphiques que j'ai pu trouver jusqu'à présent sur tout l'écran. Dans votre code, les lignes noires sont-elles dessinées sur un graphique qui occupe un écran complet ou juste une partie de l'écran? Quelle partie de votre code traite de cela?


C'est la seule ligne de l'activité qui compte: setContentView (r.layout.activity_main); Maintenant, regardons Github.com/gardarh/android- unlybitmapDrawing / blob / maître / res / ... : Vous verrez ceci: Ce qui nous amène à GITUB.COM/GARDARH/ADROID-GLYBITMAPDRAWING/BLOB/Master/SRC / ... - où tout le travail est fait à ONDRAW (). Le système appelle ONDRAW () pour moi chaque fois que cela semble avoir besoin de redessiner l'écran, il est donc automatique.


La taille de la vue est contrôlée par le fichier XML de mise en page (dans mon cas layout_height and Layout_Width est défini sur Match_Parent qui remplit l'écran), mais vous pouvez la définir sur une largeur fixe, par exemple. Layout_width = "100 dp" layout_height = "100 dp". En espérant que ça aide, bonne chance!


3 Réponses :


0
votes

Je suis en désaccord que vous économisez beaucoup en allant la route bitmap. Vous pouvez envisager une structure de données qui stocke le signal dessiné et la convertir en un objet JSON pouvant être sérialisé / désérialisé. Quant à votre question, il s'agit d'une supposition éduquée, mais elle a plus à voir avec le redéfinissement du signal dessiné, car vous n'utilisez pas GetHeight () lorsque vous créez le bitmap.


1 commentaires

L'utilisation d'un bitmap enregistre beaucoup de temps, je l'ai mesuré. Notez que cela une seule fraction d'un dessin plus grand. Le bitmap ne doit pas être mis à l'échelle du tout, la signature Canvas.Drawbitmap () que j'utilise ne doit pas échouer le bitmap - J'utilise la constante 200 au lieu de la méthode GetHeight () de simplification, cela ne devrait pas avoir d'importance. Il existe d'autres moyens potentiels de le faire, par exemple Utilisez superfailletView. Cependant, je ne suis plus intéressé que pour savoir pourquoi il y a une différence dans les images résultantes.



3
votes

La raison des différences est que le dessin en toile est effectué par accélération matérielle (GPU) et le dessin bitmap est effectué par logiciel (CPU). Si vous désactivez l'accélération matérielle, ils deviennent exactement les mêmes. Si vous multipliez les coordonnées X par 10, vous verrez que la différence est dans la manière dont les lignes sont jointes. Ce sont une différence mineure d'une pixelle et je ne me dérangerais pas avec eux. Je ne suis pas sûr que l'on est plus précis, ils semblent simplement des implémentations légèrement différentes.


1 commentaires

C'est vrai, vérifié par la désactivation de l'accélération HW. Quelle est impair, cependant.



3
votes

Android Framework API fournit des API de dessin 2D pour une animation simple qui ne nécessite pas de changements dynamiques majeurs. Il y a deux façons de la mise en œuvre à l'aide de ces API.

1. Dessiner à une vue
2. Dessin sur une toile forte> p>

1.Drawing Un cercle pour voir strong>


Dessin à la vue est une meilleure option lorsque votre UI ne nécessite pas de modifications dynamiques de l'application. Cela peut être réalisé simplement en étendant la classe de visualisation et en définissant une méthode de rappel ONDRAW () forte>. de
Utilisez la toile donnée à vous pour tous vos dessins,
Utilisation de diverses méthodes ... () (ex: Canvas.Drawcircle (X / 2, Y / 2, rayon, peinture);). ONDRAW () est une méthode de rappel invoqué lorsque la vue est initialement dessinée. p>

ci-dessous est un code d'exemple simple pour dessiner un cercle: -


MainActivity.java strong>

p> xxx pré>

2. Dessin rectangle sur une toile forte>

P>

Pour dessiner des graphiques 2D dynamiques 2D où dans votre application doit être régulièrement record, le dessin sur une toile est une meilleure option. Une toile fonctionne pour vous comme une interface, à la surface réelle sur laquelle vos graphismes seront tirés. P>

Si vous devez créer une nouvelle toile, vous devez définir le bitmap sur lequel le dessin sera effectivement être effectué. Le bitmap est toujours requis pour une toile.

L'exemple ci-dessous explique pour dessiner un rectangle: -

activité_main.xml strong>

p> xxx pré>

maintacivit.java strong>
p>

public class MainActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Paint paint = new Paint();
        paint.setColor(Color.parseColor("#DD4N5C"));
        Bitmap bitmap = Bitmap.createBitmap(512, 800, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap); 
        canvas.drawRect(150, 150, 250, 250, paint); 
        LinearLayout layout = (LinearLayout) findViewById(R.id.mylayout);
        layout.setBackgroundDrawable(new BitmapDrawable(bitmap));   
     }

     }


0 commentaires