studio programacion herramientas fundamentos con avanzado aplicaciones android android-canvas smooth-scrolling

programacion - manual de android en pdf



Desplazando un lienzo suavemente en Android (5)

Soy nuevo en Android.

Estoy dibujando mapas de bits, líneas y formas en un Lienzo dentro del método OnDraw (Lienzo de lienzo) de mi vista. Estoy buscando ayuda sobre cómo implementar un desplazamiento suave en respuesta a un arrastre por parte del usuario. He buscado pero no he encontrado ningún tutorial para ayudarme con esto.

La referencia para Canvas parece decir que si un Canvas se construye a partir de un mapa de bits (llamado bmpBuffer, por ejemplo) entonces cualquier cosa dibujada en el Canvas también se dibuja en bmpBuffer. ¿Sería posible utilizar bmpBuffer para implementar un desplazamiento ... tal vez copiarlo de nuevo en el lienzo cambiado por unos pocos píxeles a la vez? Pero si uso Canvas.drawBitmap para dibujar bmpBuffer de nuevo en Canvas desplazado unos pocos píxeles, ¿no se corromperá bmpBuffer? Quizás, por lo tanto, debería copiar bmpBuffer a bmpBuffer2 y luego dibujar bmpBuffer2 de nuevo en el lienzo.

Un enfoque más directo sería dibujar líneas, formas, etc. directamente en un mapa de bits de la memoria intermedia y luego dibujar esa memoria intermedia (con un cambio) en el lienzo, pero hasta donde puedo ver los distintos métodos: drawLine (), drawShape () y así sucesivamente no están disponibles para dibujar en un mapa de bits ... solo en un lienzo.

¿Podría tener 2 lonas? ¿Uno de los cuales se construiría a partir del mapa de bits del búfer y se usaría simplemente para trazar líneas, formas, etc. y luego el mapa de bits del búfer se dibujaría en el otro lienzo para mostrarlo en la Vista?

Debería dar la bienvenida a cualquier consejo!

Las respuestas a preguntas similares aquí (y en otros sitios web) se refieren a "blitting". Entiendo el concepto, pero no puedo encontrar nada sobre "blit" o "bitblt" en la documentación de Android. ¿Canvas.drawBitmap y Bitmap.Copy equivalentes de Android?


Continuación de la respuesta a Viktor ...

De hecho, la situación es más complicada. Debido a que el proceso de doDrawing es bastante lento (tarda 2-3 segundos en mi viejo y lento teléfono HTC Hero), me pareció deseable que aparezca un mensaje de Toast para avisar al usuario de que estaba sucediendo y para indicar el motivo. La forma obvia de hacer esto fue crear un nuevo método que contenga solo 2 líneas:

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

y para llamar a este método desde otros lugares en mi programa en lugar de doDrawing ().

Sin embargo, encontré que la tostadora nunca apareció o se encendió tan brevemente que no se pudo leer. Mi solución ha sido utilizar un controlador de verificación de tiempo para forzar al programa a dormir durante 200 milisegundos entre mostrar el Toast y llamar a doDrawing (). Aunque esto retrasa ligeramente el inicio de un redibujo, creo que este es un precio que vale la pena pagar en términos de la facilidad de uso del programa porque el usuario sabe lo que está pasando. reDrawBuffer () ahora lee:

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

y el código del controlador (que está anidado dentro de mi clase de vista) es:

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); } }`


No hay necesidad de reiniciar la actividad! (De acuerdo con la respuesta de prepbgg del 27 de enero a su ''respuesta'' del 17 de enero) En lugar de reciclar el mapa de bits e incurrir en la sobrecarga de tener la actividad recargada, puede evitar que se cargue la aplicación poniendo el atributo ''android: configChanges'' que se muestra a continuación. en el elemento ''actividad'' del archivo AndroidManifest.xml para la aplicación. Esto le indica al sistema que la aplicación manejará los cambios de orientación y que no necesita reiniciar la aplicación.

<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>

Este método se puede utilizar para obtener una notificación cuando se cambia la orientación:

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


Parece que he encontrado una respuesta. He puesto la mayor parte del código de dibujo (que anteriormente estaba en onDraw ()) en un nuevo método doDrawing (). Este método comienza creando un nuevo mapa de bits más grande que la pantalla (lo suficientemente grande como para contener el dibujo completo). A continuación, crea un segundo lienzo en el que hacer el dibujo detallado:

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

El resto del método doDrawing () se retoma con el dibujo detallado de BufferCanvas.

El método completo de onDraw () ahora se lee de la siguiente manera:

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

Las variables de posición, posX y posY, se inicializan en 0 en el método onCreate () de la aplicación. La aplicación implementa OnGestureListener y utiliza los argumentos distanceX y distanceY devueltos en la notificación de OnScroll para incrementar posX y posY.

Eso parece ser todo lo que se necesita para implementar un desplazamiento suave. ¿O estoy mirando algo?


Yo tuve este problema también,

Hice el dibujo de esta manera:

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); }

para un desplazamiento suave, necesitaría hacer algún tipo de método que tome algunos puntos después del desplazamiento (es decir, el primer punto de desplazamiento y el décimo), restar esos y desplazarse por ese número en cada bucle que lo hace gradualmente más lento (ScrollAmount - Giros - Fricción).

Espero que esto le dé un poco más de visión.


prepbgg: no creo que el código funcione porque canvas.drawBitmap no dibuja en el mapa de bits, sino que dibuja el mapa de bits en el lienzo.

¡Corrígeme si estoy equivocado!