studio proyectos programacion para guia desarrollo avanzado aplicaciones java android android-animation android-view android-gesture

java - proyectos - Diferente velocidad de lanzamiento(deslizamiento) en diferentes dispositivos Android con la misma densidad



manual programacion android (3)

¿Por qué diferentes dispositivos con la misma densidad y casi el mismo nivel de api no tienen la misma velocidad máxima?

Los parámetros de velocidad mínima y máxima son establecidos por el fabricante. Los diferentes modelos de dispositivos a menudo usarán el mismo cubo de densidad para la selección de recursos, pero normalmente no comparten la misma densidad física . Suponga la existencia de un teléfono de 4 "y un teléfono de 5" con resoluciones idénticas y una densidad informada idéntica de 1.5. Imagina deslizar ambas pantallas a la misma velocidad física . Los píxeles / segundo informados serían más altos en la pantalla pequeña a pesar del hecho de que ambos teléfonos tienen resoluciones y densidades reportadas idénticas.

¿Qué hacer con la velocidad mínima y máxima? Digamos que el fabricante de la pantalla más pequeña determina que 75 píxeles / segundo es la velocidad mínima perfecta del dedo antes de informar un gesto de lanzamiento. Cualquier más pequeño resultaría en lanzamientos accidentales por error de toque, cualquier más grande requeriría un gesto demasiado deliberado para lanzar algo. Si el fabricante del teléfono grande quisiera igualar el mismo comportamiento físico perfecto (la misma velocidad del dedo) del teléfono más pequeño, necesitaría ajustar la velocidad mínima para que sea un número menor. El fabricante del dispositivo más grande requeriría menos píxeles / segundo para iniciar un lanzamiento debido a las características físicas. Otros factores como la sensibilidad de la pantalla probablemente influyen en diferentes fabricantes.

¿Cómo puedo obtener la misma experiencia en diferentes dispositivos cuando un usuario hace un gesto de deslizar?

Usa la velocidad dada en píxeles / segundo para configurar las animaciones. Simplemente evite el uso de parámetros independientes de densidad y debería poder ajustar la velocidad exactamente. Tenga en cuenta que esto no tiene nada que ver con los valores de velocidad mínima o máxima. Sin embargo, desearía calcular su SWIPE_THRESHOLD_VELOCITY para que sea un valor de píxel "sin procesar" según la densidad indicada. Así es como el Launcher2 de Android calcula la velocidad de umbral independiente de la densidad para los lanzamientos de elementos de la pantalla de inicio:

int DENSITY_INDEPENDENT_THRESHOLD = 200; Resources r = getResources(); float density = r.getDisplayMetrics().density; SWIPE_THRESHOLD_VELOCITY = (int)(DENSITY_INDEPENDENT_THRESHOLD * density);

Tenga en cuenta que este umbral sería el mismo para el teléfono de 4 "y el de 5" en el ejemplo anterior. Esto no afecta las velocidades reales porque solo estamos hablando de un umbral aquí. Simplemente necesita deslizar un 20% más rápido en el teléfono de 5 "que en el de 4" para romper el umbral. El lanzador de Android usa un DENSITY_INDEPENDENT_THRESHOLD de -1500 en la dirección y, pero 200 suena bien para su aplicación.

¿Puedo usar los datos de velocidad máxima para lograr una experiencia uniforme en todos los dispositivos Android?

No. La velocidad máxima es un caso extremo que no necesita para animar correctamente. Dudo que los usuarios arrojen algo a la velocidad máxima a menos que estén jugando un juego, y a los usuarios no les importará si la animación coincide perfectamente a una velocidad de 6000 píxeles / segundo de todos modos.

TL; DR Utilice velocidades brutas de los argumentos de onFling para configurar animaciones y velocidades exactas. Evite utilizar parámetros independientes de densidad para configurar animaciones de lanzamiento.

Estoy escribiendo mi propio visor de imágenes que permite a los usuarios deslizar hacia la izquierda / derecha para ver la siguiente / imagen anterior. Quiero animar el cambio de imagen de acuerdo a la velocidad del lanzamiento.

Para detectar un gesto de lanzamiento y su velocidad, seguí esta detección básica de gesto e hice lo que la respuesta aceptada sugería:

public class SelectFilterActivity extends Activity implements OnClickListener { private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private GestureDetector gestureDetector; View.OnTouchListener gestureListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* ... */ // Gesture detection gestureDetector = new GestureDetector(this, new MyGestureDetector()); gestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }; } class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show(); } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // nothing } return false; } }

El problema es que obtengo diferentes valores de velocidad (velocidad X y velocidad Y) para diferentes dispositivos Android con la misma densidad. Básicamente, significa que en un dispositivo el deslizamiento se siente lento y no sensible, y otros dispositivos se sienten demasiado sensibles.

Pensé que podría tener algo que ver con la velocidad máxima "predeterminada" en el dispositivo, que se puede recuperar utilizando -

ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity()

Los resultados en diferentes dispositivos con la misma densidad no son los mismos que se esperaban:

Samsung S I 480x800 density 1.5 Android 2.1 getScaledMinimumFlingVelocity(): 75 getScaledMaximumFlingVelocity(): 3600 ViewConfiguration.MAXIMUM_FLING_VELOCITY = 4000 HTC Desire 480x800 density 1.5 Android 2.3.3 getScaledMinimumFlingVelocity(): 75 getScaledMaximumFlingVelocity(): 6000 ViewConfiguration.MAXIMUM_FLING_VELOCITY = 4000 Samsung S III mini 480x800 density 1.5 Android 4.1 getScaledMinimumFlingVelocity(): 75 getScaledMaximumFlingVelocity(): 12000 ViewConfiguration.MAXIMUM_FLING_VELOCITY = 8000

También puede ver que ViewConfiguration tiene 2 valores diferentes para MAXIMUM_FLING_VELOCITY en Android por debajo de 4.0 y superior.

¿Por qué diferentes dispositivos con la misma densidad y casi el mismo nivel de api no tienen la misma velocidad máxima? ¿Cómo puedo obtener la misma experiencia en diferentes dispositivos cuando un usuario hace un gesto de deslizar? ¿Puedo usar los datos de velocidad máxima para lograr una experiencia uniforme en todos los dispositivos Android?


No uses la velocidad: no es fácil de usar. Un golpe a la derecha es un número +, a la izquierda es un número. Usted podría estos:

event1.getRawY() event2.getRawY() event1.getRawX() event2.getRawX()

para determinar si el golpe fue hacia la izquierda o hacia la derecha:

si el primer evento fue más que el segundo, la persona se deslizó hacia la izquierda, pero puede decir si el último evento fue x menos que el primer evento, entonces el golpe de la persona fue lo suficientemente lejos y reaccionar a él. Usted puede hacer lo contrario para un deslizamiento estaba a la derecha. Además, el onFling no reconoce pequeños toques y solo toca, por lo que puede escapar sin comparar la velocidad o la longitud de la distancia.


Tuve un problema similar. En lugar de trabajar directamente con las velocidades de ViewConfiguration máxima y mínima de ViewConfiguration , puede normalizar la velocidad a un valor entre 0 y 1.

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { float maxFlingVelocity = ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity(); float velocityPercentX = velocityX / maxFlingVelocity; // the percent is a value in the range of (0, 1] float normalizedVelocityX = velocityPercentX * PIXELS_PER_SECOND; // where PIXELS_PER_SECOND is a device-independent measurement

En otras palabras, velocityPercentX le da la "potencia" del lanzamiento como porcentaje, y normalizedVelocityX es la velocidad en términos de la lógica de su aplicación (como el ancho de una imagen en píxeles independientes del dispositivo).