studio left detector android android-activity swipe ontouchlistener

left - gesture android studio



Terminar la actividad en el golpe derecho? (5)

Tengo que terminar la Activity cuando el usuario ofrezca un golpe correcto en cualquier lugar de la pantalla. Lo he intentado con GestureDetector y funciona bien si no hay ScrollView ni existe RescyclerView en la Activity y, además, las vistas que tienen onClickListener tampoco permiten detectar el deslizamiento sobre ellas. Así que lo intenté de otra manera al superponer una vista en el diseño en la parte superior de todos ellos programáticamente, luego traté de detectar el evento de deslizamiento sobre él.

private void swipeOverToExit(ViewGroup rootView) { OverlayLayout child = new OverlayLayout(this); ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); child.setLayoutParams(layoutParams); rootView.addView(child); }

OverlayLayout

public class OverlayLayout extends RelativeLayout { private float x1, x2; private final int MIN_DISTANCE = 150; public OverlayLayout(Context context) { super(context); } public OverlayLayout(Context context, AttributeSet attrs) { super(context, attrs); } public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { /* * This method JUST determines whether we want to intercept the motion. * If we return true, onTouchEvent will be called and we do the actual * logic there. */ final int action = MotionEventCompat.getActionMasked(event); Logger.logD("Intercept===", action + ""); // Always handle the case of the touch gesture being complete. if (action == MotionEvent.ACTION_DOWN) { return true; // Intercept touch event, let the parent handle swipe } Logger.logD("===", "Out side" + action + ""); // In general, we don''t want to intercept touch events. They should be // handled by the child view. return false; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: x1 = event.getX(); break; case MotionEvent.ACTION_UP: x2 = event.getX(); float deltaX = x2 - x1; if (Math.abs(deltaX) > MIN_DISTANCE) { Logger.logD("Swipe Right===", MIN_DISTANCE + ""); return true; } else { Logger.logD("Tap===", "Tap==="); return super.onTouchEvent(event); } } return true; } }

La lógica es interceptar el evento táctil a otra vista si la acción de deslizamiento se realiza sobre el OverlayLayout luego termina la Activity . Sin embargo, ahora puedo detectar el evento de deslizamiento en OverlayLayout pero otras vistas no pudieron responder a pesar de que tuve un retorno de return super.onTouchEvent(event); en otra condición de onTouchEvent como u puede averiguar ahí en mi código. Cualquiera por favor ayúdame a hacerlo. Estoy atrapado aquí y muy emocionado de aprender el truco :)


Creo que el problema que tienes con RecyclerView y ScrollView tiene que ver con que los elementos secundarios obtengan el enfoque antes que los padres. puede intentar configurar el android:descendantFocusability="beforeDescendants" para las vistas Recycler / Scroll.


He enfrentado el mismo problema con respecto a la Superposición de Actividades. Esto funciono para mi

1) Define tu SwipeListener

La clase pública SwipeListener implementa View.OnTouchListener {

private SwipeListenerInterface activity; private float downX, downY, upX, upY; public SwipeListener(SwipeListenerInterface activity) { this.activity = activity; } public void onRightToLeftSwipe(View v) { Log.i(logTag, "RightToLeftSwipe!"); activity.onRightToLeftSwipe(v); } public void onLeftToRightSwipe(View v) { Log.i(logTag, "LeftToRightSwipe!"); activity.onLeftToRightSwipe(v); } public void onTopToBottomSwipe(View v) { Log.i(logTag, "TopToBottomSwipe!"); activity.onTopToBottomSwipe(v); } public void onBottomToTopSwipe(View v) { Log.i(logTag, "BottomToTopSwipe!"); activity.onBottomToTopSwipe(v); } public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { downX = event.getX(); downY = event.getY(); return true; } case MotionEvent.ACTION_UP: { upX = event.getX(); upY = event.getY(); float deltaX = downX - upX; float deltaY = downY - upY; if (deltaX < 0 ) { this.onLeftToRightSwipe(v); return true; } if (deltaX > 0 ) { this.onRightToLeftSwipe(v); return true; } if (deltaY < 0) { this.onTopToBottomSwipe(v); return true; } if (deltaY > 0) { this.onBottomToTopSwipe(v); return true; } } } return false; } public void setSwipeRestrictions(int swipeRestrictionX, int swipeRestrictionY) { this.swipeRestrictionX = swipeRestrictionX; this.swipeRestrictionY = swipeRestrictionY; }

2) Con la siguiente interfaz referida

public interface SwipeListenerInterface { void onRightToLeftSwipe(View v); void onLeftToRightSwipe(View v); void onTopToBottomSwipe(View v); void onBottomToTopSwipe(View v); }

3) Cree el objeto y vincúlelo a su overlayView (asegúrese de ajustar la interfaz a la vista de OverLay para que pueda recibir las devoluciones de llamada)

sl = new SwipeListener(this); overlayView.setOnTouchListener(sl);


Lo que intentas hacer es básicamente el comportamiento predeterminado en Android Wear y se considera como una práctica estándar en los Android Watches para salir de una aplicación. En Android usa DismissOverlayView hace todo el trabajo pesado para ti.

Los teléfonos inteligentes tienen el botón de retroceso, mientras que el desgaste se basa en el patrón de desconexión prolongada o de deslizamiento para salir de la pantalla. Debe descartar la actividad en la prensa trasera, mezclando el patrón de desgaste en los teléfonos inteligentes Android hará que el usuario se sienta confundido. Al menos mostrar un diálogo de advertencia para evitar la salida accidental.

Solución

Como veo, esta pregunta está etiquetada con Activity Android. Le sugiero que realice una Actividad de Base que se ocupe del gesto de deslizar y finish() sí misma de izquierda a derecha.

La clase de actividad base debería verse así:

public abstract class SwipeDismissBaseActivity extends AppCompatActivity { 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; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); gestureDetector = new GestureDetector(new SwipeDetector()); } private class SwipeDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH, // then dismiss the swipe. if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // Swipe from left to right. // The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) // and a certain velocity (SWIPE_THRESHOLD_VELOCITY). if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { finish(); return true; } return false; } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // TouchEvent dispatcher. if (gestureDetector != null) { if (gestureDetector.onTouchEvent(ev)) // If the gestureDetector handles the event, a swipe has been // executed and no more needs to be done. return true; } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } }

Ahora puede hacer que otras actividades amplíen esta actividad básica y la Inheritance les hará adoptar automáticamente el pase para descartar el comportamiento.

public class SomeActivity extends SwipeDismissBaseActivity {

Ventajas de esta manera.

  • Puramente enfoque OOPS
  • Código limpio: no es necesario escribir un detector de deslizamiento en cada tipo de diseño utilizado en el proyecto (relativo, lineal, etc.)
  • Funciona perfectamente en ScrollView

SwipeBack es una biblioteca de Android que permite a Activities hacer lo mismo que el "botón de retroceso" de Android, pero de una manera muy intuitiva utilizando un gesto de deslizar.

Consíguelo de maven central

compile ''com.hannesdorfmann:swipeback:1.0.4''

Crea una actividad base y anota el método.

public void initDrawerSwipe(int layoutId) { SwipeBack.attach(this, Position.LEFT) .setContentView(layoutId) .setSwipeBackView(R.layout.layout_swipe_back) .setSwipeBackTransformer(new SlideSwipeBackTransformer() { @Override public void onSwipeBackCompleted(SwipeBack swipeBack, Activity activity) { supportFinishAfterTransition(); } }); }

Luego, pase su ID de diseño al método que colocó en su actividad base

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); initDrawerSwipe(R.layout.activity_stylists); }

Esto funciona bien en todos los escenarios que haya señalado en su consulta.


Prueba esto. Estoy usando la función para deslizar así.

Ver para deslizar ...

yourview.setOnTouchListener(new SimpleGestureFilter(this)); // yourview is layout or container to swipe

Clase SimpleGestureFilter

public class SimpleGestureFilter implements View.OnTouchListener { static final String logTag = "ActivitySwipeDetector"; private Context activity; static final int MIN_DISTANCE = 100;// TODO change this runtime based on screen resolution. for 1920x1080 is to small the 100 distance private float downX, downY, upX, upY; // private NDAAgreementActivity mMainActivity; public SimpleGestureFilter(Context mainActivity) { activity = mainActivity; } public void onRightToLeftSwipe() { //do your code to right to left } public void onLeftToRightSwipe() { //do your code to left to right } public void onTopToBottomSwipe() { } public void onBottomToTopSwipe() { } public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { downX = event.getX(); downY = event.getY(); return true; } case MotionEvent.ACTION_UP: { upX = event.getX(); upY = event.getY(); float deltaX = downX - upX; float deltaY = downY - upY; // swipe horizontal? if (Math.abs(deltaX) > MIN_DISTANCE) { // left or right if (deltaX < 0) { this.onLeftToRightSwipe(); return true; } if (deltaX > 0) { this.onRightToLeftSwipe(); return true; } } else { Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long horizontally, need at least " + MIN_DISTANCE); // return false; // We don''t consume the event } // swipe vertical? if (Math.abs(deltaY) > MIN_DISTANCE) { // top or down if (deltaY < 0) { this.onTopToBottomSwipe(); return true; } if (deltaY > 0) { this.onBottomToTopSwipe(); return true; } } else { Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long vertically, need at least " + MIN_DISTANCE); // return false; // We don''t consume the event } return false; // no swipe horizontally and no swipe vertically }// case MotionEvent.ACTION_UP: } return false; } }