Отключить прокрутку в списке - PullRequest
42 голосов
/ 30 сентября 2011

У меня есть представление списка, и в зависимости от какой-то логики я хочу временно отключить прокрутку. view.setOnScrollListener (нуль); мне не помогает, я думаю, мне нужно написать какой-нибудь код, может кто-нибудь дать мне историю или какой-нибудь фрагмент?

Спасибо

Ответы [ 10 ]

43 голосов
/ 03 октября 2012

Другим вариантом без создания нового пользовательского ListView было бы присоединение onTouchListener к вашему ListView и возвращение true в обратном вызове onTouch(), если действие события движения ACTION_MOVE.

listView.setOnTouchListener(new OnTouchListener() {

    public boolean onTouch(View v, MotionEvent event) {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});
42 голосов
/ 21 июня 2012

В вашем CustomListView:

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

Тогда ListView будет реагировать на нажатия, но не будет изменять позицию прокрутки.

27 голосов
/ 01 декабря 2014

используйте listview.setEnabled (false) , чтобы отключить прокрутку списка

Примечание: это также отключает выбор строки

8 голосов
/ 09 сентября 2013

Если у вас есть событие, связанное с элементами списка, то перетаскивание списка с любым из этих решений все равно вызовет событие.Вы хотите использовать следующий метод для учета ожиданий пользователей отменить событие, перетаскивая его из выбранного элемента (адаптировано из ответа 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);
}

Доступен полный класс настраиваемого представления: https://gist.github.com/danosipov/6498490

7 голосов
/ 02 октября 2011

сделай CustomListView

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

на false ребенок будет обрабатывать событие касания, убедитесь, что вы поставили if condition, чтобы проверить, нужно ли вам прокручивать или нет.

5 голосов
/ 22 октября 2014

Лучший ответ для меня - Дан Осипов.Я бы улучшил это так.(запуск события действия ОТМЕНА вместо ручного стирания нажатого состояния).

@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);
}
2 голосов
/ 06 августа 2014

При написании кода для удаления, отображаемого в виде списка, я хотел предотвратить вертикальную прокрутку после обнаружения удара. Я установил логический флаг в разделе ACTION_MOVE, как только удастся выполнить условия для удаления. Метод dispatchTouchEvent проверяет это условие и предотвращает работу прокрутки. В ACTION_UP я установил флаг обратно в false, чтобы снова включить прокрутку.

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);
}
1 голос
/ 21 июля 2015

Попробуйте это:

listViewObject.setTranscriptMode(0);

У меня работает.

1 голос
/ 08 мая 2015

Это код, на который указал Джо Блоу (комментарий к сообщению OP) на http://danosipov.com/?p=604, но я выкладываю его здесь, чтобы сохранить его на случай, если ссылка потеряла:

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

Когда вы добавляете этот ListView в свой макет, не забудьте добавить к нему имя пакета, в противном случае при попытке его раздувания возникнет исключительная ситуация.

1 голос
/ 20 октября 2014

Мой ответ будет интересен пользователям Xamarin и MvvmCross.Основная концепция та же, что и в предыдущих сообщениях, поэтому основные шаги:

  1. Отключение событий прокрутки
  2. Динамическое изменение высоты списка

Здесь вы помогаетекласс, позволяющий отключить прокрутку в виде списка:

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 ();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...