studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android listview scroll listener

android - programacion - Deshabilitar el desplazamiento en lista



manual de programacion android pdf (10)

Al escribir código para deslizar para eliminar en una vista de lista, quería evitar el desplazamiento vertical una vez que se había detectado el deslizamiento. Establecí un indicador booleano en la sección ACTION_MOVE una vez que se ha cumplido el deslizamiento para eliminar las condiciones. El método dispatchTouchEvent comprueba esa condición y evita que el desplazamiento funcione. En ACTION_UP, configuro nuevamente la bandera en falso para volver a habilitar el desplazamiento.

private float mY = Float.NaN; private boolean mStopScroll = false; @Override public boolean onTouch(View view, MotionEvent event) { if(!mStopScroll) { mY = event.getY(); } switch (event.getAction()) { case MotionEvent.ACTION_MOVE: if(<condition that stops the vertical scroll>) { mStopScroll = true; } break; case MotionEvent.ACTION_UP: mStopScroll = false; // your code here return true; default: } return false; } @Override public boolean dispatchTouchEvent(MotionEvent motionEvent) { if(mStopScroll) { motionEvent.setLocation(motionEvent.getX(), mY); } return super.dispatchTouchEvent(motionEvent); }

Tengo una vista de lista y, dependiendo de alguna lógica, deseo desactivar temporalmente el desplazamiento. view.setOnScrollListener (null); no me ayuda, creo que necesito escribir un código, ¿alguien me puede dar una historia o algún fragmento?

Gracias


En su CustomListView:

@Override public boolean dispatchTouchEvent(MotionEvent ev){ if(ev.getAction()==MotionEvent.ACTION_MOVE) return true; return super.dispatchTouchEvent(ev); }

Entonces, ListView reaccionará a los clics, pero no cambiará la posición de desplazamiento.


Este es el código Joe Blow (comentario en la publicación OP) señalado en danosipov.com/?p=604 pero lo estoy publicando aquí para preservarlo en caso de que el enlace quede huérfano:

public class ScrollDisabledListView extends ListView { private int mPosition; public ScrollDisabledListView(Context context) { super(context); } public ScrollDisabledListView(Context context, AttributeSet attrs) { super(context, attrs); } public ScrollDisabledListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; if (actionMasked == MotionEvent.ACTION_DOWN) { // Record the position the list the touch landed on mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); return super.dispatchTouchEvent(ev); } if (actionMasked == MotionEvent.ACTION_MOVE) { // Ignore move events return true; } if (actionMasked == MotionEvent.ACTION_UP) { // Check if we are still within the same view if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) { super.dispatchTouchEvent(ev); } else { // Clear pressed state, cancel the action setPressed(false); invalidate(); return true; } } return super.dispatchTouchEvent(ev); } }

Cuando agrega este ListView a su diseño, recuerde que debe precederlo con su nombre de paquete; de ​​lo contrario, se generará una excepción cuando intente inflarlo.


La mejor respuesta para mí es la de Dan Osipov. Lo mejoraría así. (disparando un evento de acción CANCELAR en lugar de borrar manualmente el estado presionado).

@Override public boolean dispatchTouchEvent(MotionEvent ev) { final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; if (actionMasked == MotionEvent.ACTION_DOWN) { // Record the position the list the touch landed on mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); return super.dispatchTouchEvent(ev); } if (actionMasked == MotionEvent.ACTION_MOVE) { // Ignore move events return true; } if (actionMasked == MotionEvent.ACTION_UP) { // Check if we are still within the same view if (pointToPosition((int) ev.getX(), (int) ev.getY()) != mPosition) { // Clear pressed state, cancel the action ev.setAction(MotionEvent.ACTION_CANCEL); } } return super.dispatchTouchEvent(ev); }


Mi respuesta será interesante para los usuarios de Xamarin y MvvmCross. El concepto principal es el mismo que en las publicaciones anteriores, por lo que los pasos principales son:

  1. Silenciar eventos de desplazamiento
  2. Cambiar dinámicamente la altura de la lista

Aquí está la clase de ayuda, que permite deshabilitar el desplazamiento en la vista de lista:

using System; using Cirrious.MvvmCross.Binding.Droid.Views; using Android.Content; using Android.Util; using Android.Views; using Android.Database; namespace MyProject.Android.Helpers { public class UnscrollableMvxListView : MvxListView { private MyObserver _myObserver; public UnscrollableMvxListView (Context context, IAttributeSet attrs, MvxAdapter adapter) : base(context, attrs, adapter) { } protected override void OnAttachedToWindow () { base.OnAttachedToWindow (); var dtso = new MyObserver(this); _myObserver = dtso; Adapter.RegisterDataSetObserver (dtso); } protected override void OnDetachedFromWindow () { Log.Debug ("UnscrollableMvxListView", "OnDetachedFromWindow"); if (_myObserver != null) { Adapter.UnregisterDataSetObserver (_myObserver); _myObserver = null; } base.OnDetachedFromWindow (); } //Make List Unscrollable private int _position; public override bool DispatchTouchEvent (MotionEvent ev) { MotionEventActions actionMasked = ev.ActionMasked & MotionEventActions.Mask; if (actionMasked == MotionEventActions.Down) { // Record the position the list the touch landed on _position = PointToPosition((int) ev.GetX (), (int) ev.GetY()); return base.DispatchTouchEvent(ev); } if (actionMasked == MotionEventActions.Move) { // Ignore move events return true; } if (actionMasked == MotionEventActions.Up) { // Check if we are still within the same view if (PointToPosition((int) ev.GetX(), (int) ev.GetY()) == _position) { base.DispatchTouchEvent(ev); } else { // Clear pressed state, cancel the action Pressed = false; Invalidate(); return true; } } return base.DispatchTouchEvent(ev); } //Make List Flat public void JustifyListViewHeightBasedOnChildren () { if (Adapter == null) { return; } var vg = this as ViewGroup; int totalHeight = 0; for (int i = 0; i < Adapter.Count; i++) { View listItem = Adapter.GetView(i, null, vg); listItem.Measure(0, 0); totalHeight += listItem.MeasuredHeight; } ViewGroup.LayoutParams par = LayoutParameters; par.Height = totalHeight + (DividerHeight * (Adapter.Count - 1)); LayoutParameters = par; RequestLayout(); } } internal class MyObserver : DataSetObserver { private readonly UnscrollableMvxListView _unscrollableMvxListView; public MyObserver (UnscrollableMvxListView lst) { _unscrollableMvxListView = lst; } public override void OnChanged() { Log.Debug("UnscrollableMvxListView", "OnChanged"); base.OnChanged (); _unscrollableMvxListView.JustifyListViewHeightBasedOnChildren (); } } }


Otra opción sin crear un nuevo ListView personalizado sería adjuntar un onTouchListener a su ListView y devolver true en la devolución de llamada onTouch() si la acción de evento de movimiento es ACTION_MOVE .

listView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { return (event.getAction() == MotionEvent.ACTION_MOVE); } });


Prueba esto:

listViewObject.setTranscriptMode(0);

Funciona para mi.


Si tiene un evento vinculado a los elementos de la lista, al arrastrar la lista con cualquiera de estas soluciones se desencadenará el evento. Desea utilizar el siguiente método para tener en cuenta la expectativa de los usuarios de cancelar el evento arrastrándose desde el elemento seleccionado (adaptado de la respuesta de Pointer Null):

@Override public boolean dispatchTouchEvent(MotionEvent ev) { final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK; if (actionMasked == MotionEvent.ACTION_DOWN) { // Record the position the list the touch landed on mPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); return super.dispatchTouchEvent(ev); } if (actionMasked == MotionEvent.ACTION_MOVE) { // Ignore move events return true; } if (actionMasked == MotionEvent.ACTION_UP) { // Check if we are still within the same view if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) { super.dispatchTouchEvent(ev); } else { // Clear pressed state, cancel the action setPressed(false); invalidate(); return true; } } return super.dispatchTouchEvent(ev); }

La clase de vista personalizada completa está disponible: https://gist.github.com/danosipov/6498490


hacer su CustomListView

@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(needToStop){ return false;} return super.onInterceptTouchEvent(ev); }

en false los niños manejarán el evento táctil, asegúrese de poner su if condition para verificar que necesita desplazarse o no.


use listview.setEnabled (false) para deshabilitar el desplazamiento de la vista de lista

Nota: Esto también desactiva las selecciones de fila