Question

Je suis nouveau à Android.

Je dessine bitmaps, des lignes et des formes sur une toile dans la méthode OnDraw (toile Canvas) de mon avis. Je suis à la recherche de l'aide sur la façon de mettre en œuvre un défilement fluide en réponse à un déplacement par l'utilisateur. J'ai cherché mais pas trouvé de tutoriels pour me aider.

La référence pour toile semble dire que si une toile est construit à partir d'un Bitmap (appelé bmpBuffer, par exemple), alors quoi que ce soit dessiné sur la toile est également attirée sur bmpBuffer. Serait-il possible d'utiliser bmpBuffer pour mettre en œuvre un parchemin ... peut-être copier vers le canevas décalé de quelques pixels à la fois? Mais si j'utilise Canvas.drawBitmap pour dessiner bmpBuffer arrière Canvas décalé de quelques pixels, ne sera pas bmpBuffer être corrompu? Peut-être, donc je devrais copier bmpBuffer à bmpBuffer2 puis dessiner bmpBuffer2 revenir à la toile.

Une approche plus simple serait de dessiner les lignes, les formes, etc. directement dans un Bitmap tampon puis piochez tampon (avec un décalage) sur la toile, mais pour autant que je peux voir les différentes méthodes: DrawLine (), drawShape (), etc. ne sont pas disponibles pour le dessin à un Bitmap ... seulement à une toile.

Puis-je avoir 2 Canevas? Dont un serait construit à partir du bitmap tampon et utilisé simplement pour tracer les lignes, les formes, etc., puis le bitmap tampon serait tiré sur l'autre toile pour l'affichage dans la vue?

Je recevoir des conseils!

Les réponses à des questions similaires ici (et sur d'autres sites) font référence à « blitting ». Je comprends le concept, mais ne trouve rien « blit » ou « BitBlt » dans la documentation Android. Sont les équivalents de Canvas.drawBitmap et Bitmap.Copy Android?

Était-ce utile?

La solution

J'ai eu ce problème aussi,

Je l'ai fait le dessin comme ceci:

Canvas BigCanvas = new Canvas();
Bitmap BigBitmap = new Bitmap(width,height);

int ScrollPosX , ScrollPosY  // (calculate these with the onScrollEvent handler)

void onCreate()
{
   BigCanvas.SetBitmap(BigBitmap);
}

onDraw(Canvas TargetCanvas)
{
   // do drawing stuff
   // ie.  BigCanvas.Draw.... line/bitmap/anything

   //draw to the screen with the scrolloffset

   //drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
   TargetCanvas.DrawBitmap(BigBitmap(new Rect(ScrollPosX,ScrollPosY,ScrollPosX + BigBitmap.getWidth(),ScrollPosY + BigBitmap.getHeight(),new Rect(0,0,ScreenWidth,ScreenHeight),null);
}

pour vous défilement régulier auriez besoin de faire une sorte de méthode qui prend quelques points après le défilement (le premier point de défilement et le 10e), il faut soustraire ceux-ci et faites défiler par ce nombre dans un pour chaque boucle qui le rend progressivement plus lente (scrollamount - met - friction).

J'espère que cela donne une meilleure idée.

Autres conseils

Il me semble avoir trouvé une réponse. J'ai mis la plus grande partie du code de dessin (qui était auparavant dans onDraw ()) dans une nouvelle méthode doDrawing (). Cette méthode commence par la création d'une nouvelle image plus grande que l'écran (suffisamment grand pour contenir le dessin complet). Il crée ensuite une deuxième toile sur laquelle faire le dessin détaillé:

    BufferBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
    Canvas BufferCanvas = new Canvas(BufferBitmap);

Le reste de la méthode doDrawing () est repris dans le dessin détaillé de BufferCanvas.

Toute la méthode onDraw () se lit maintenant comme suit:

    @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(BufferBitmap, (float) -posX, (float) -posY, null);
}

Les variables de position, posX et posY, sont initialisés à 0 dans la méthode onCreate () de l'application. L'application met en œuvre OnGestureListener et utilise les arguments distanceX et distanceY retournés dans la notification OnScroll à incrémenter posX et posY.

Cela semble être à peu près tout ce qui est nécessaire pour mettre en œuvre un défilement fluide. Ou suis-je trop regarder quelque chose !?

Suite de la réponse à Viktor ...

En fait, la situation est plus compliquée. Parce que le processus doDrawing est assez lent (en 2-3 secondes sur mon téléphone lent vieux HTC Hero) Je l'ai trouvé souhaitable pour faire apparaître un message Toast pour informer l'utilisateur qu'il se passait et d'indiquer la raison. La façon évidente de le faire était de créer une nouvelle méthode contenant seulement 2 lignes:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");`
    doDrawing();
}

et d'appeler cette méthode à partir d'autres endroits dans mon programme au lieu de doDrawing ().

Cependant, je trouve que le pain soit jamais apparu ou flashé si brièvement qu'il ne pouvait pas être lu. Ma solution a été d'utiliser un gestionnaire de contrôle de temps pour forcer le programme à dormir pendant 200 millisecondes entre l'affichage du Toast et appelant doDrawing (). Bien que cela retarde légèrement le début d'un nouveau tracé, je pense que c'est un prix à payer en termes de facilité d'utilisation du programme parce que l'utilisateur sait ce qui se passe. reDrawBuffer () se lit maintenant:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");
    mTimeCheckHandler.sleep(200);    
}`

et le code Handler (qui est imbriqué dans ma classe View) est:

private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();

class timeCheckHandler extends Handler {
@Override
    public void handleMessage(Message msg) {
        doDrawing();
    }
    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}`

Pas besoin de l'activité à redémarrer! (Par la réponse de prepbgg 27 10 Jan à son 17 janvier 10 « réponse ») plutôt que de recycler le bitmap et encourir les frais généraux d'avoir l'activité rechargées, vous pouvez éviter d'avoir l'application chargée en mettant le 'Android: configChanges de l'attribut illustré ci-dessous, dans l'élément « d'activité » du fichier AndroidManifest.xml pour l'application. Cela indique au système la l'application va gérer les changements d'orientation et qu'il n'a pas besoin de redémarrer l'application.

<activity android:name=".ANote"
    android:label="@string/app_name"
    android:configChanges="orientation|screenLayout">
    <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Cette méthode peut être utilisée pour obtenir une notification lorsque le orienation est modifié:

public void onConfigurationChanged(Configuration  newConfig) {
    super.onConfigurationChanged(newConfig);
    prt("onConfigurationChanged: "+newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
      prt("  PORTRAIT");
    } else {
      prt("  LANDSCAPE");
    }
} // end of onConfigurationChanged

prepbgg. Je ne pense pas que le code ne fonctionnera parce que canvas.drawBitmap ne tire pas dans le bitmap, mais dessine le bitmap sur la toile

moi si je me trompe!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top