Причем решить эту задачу без использования посторонних библиотек и для всех устройств, начиная с Froyo.
Сам процесс перетаскивания элемента проблемой не является.
Проблема — отключить скроллирование списка после того, как мы уже с ним не работаем.
Дело в том, что после того как мы вытащили элемент за пределы ScrollView и перемещаем его в нужно место, ScrollView продолжает следить за нашими движениями и продолжает скроллироваться. Это не влияет на функционал, но является недопустимым с точки зрения дизайна интерфейса.
Тема достаточно простая. Я думаю, практически каждый программист способен решить эту задачу самостоятельно.
Но проблема в том, что вместо изобретения велосипеда мы часто лезем в интернет в поисках решения.
И находим. В том числе stackoverflow предлагает нам вполне «работающее» решение.
Не удивлюсь, что кто-то может его применить в своем коде без тщательной проверки…
Решение это выглядит вот так:
dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL, 0, 0, 0));
На первый взгляд — адекватное решение. И оно работает! Вот только оно ломает обработку касаний у ScrollView. Результат — падение приложения с переполнением стэка в непредсказуемый момент времени.
Решение выглядит красивым, но использовать его нельзя!
Есть решение чуть более замудрённое, но гораздо более безопасное и предсказуемое.
Необходимо расширить функционал ScrollView следующим образом:
public class ScrollViewEx extends ScrollView { protected boolean scrollActive = true; public ScrollViewEx(Context context) { super(context); } public ScrollViewEx(Context context, AttributeSet attrs){ super(context,attrs); } public ScrollViewEx(Context context, AttributeSet attrs, int defStyle){ super(context,attrs,defStyle); } public void stopScroll(){ scrollActive = false; } @Override public boolean dispatchTouchEvent(MotionEvent event){ if (event.getAction()==MotionEvent.ACTION_DOWN) scrollActive = true; if (scrollActive || event.getAction()!=MotionEvent.ACTION_MOVE) return super.dispatchTouchEvent(event); return false; } }
Здесь делается очень простая вещь — создаётся переменная, которая отвечает за отключение скролла.
Переменная выставляется программистом в нужный момент и автоматически сбрасывается при нажатии на элемент.
Всё что делает переменная — блокирует виджетом обработку события «перемещение касания».
Соответственно, в нужный момент мы вызываем метод stopScroll, после этого список продолжает обрабатывать сообщения о касаниях, но не реагирует на перемещение. Никакого скроллирования не происходит.
Если же пользователь снова нажал на список, то скроллирование включается обратно.
Задача решена. При этом код на 100% предсказуем и корректен.
ссылка на оригинал статьи http://habrahabr.ru/post/218307/
Добавить комментарий