Встраивание ListView в Галерею
-
14-10-2019 - |
Вопрос
Цель состоит в том, чтобы реализовать галерею, адаптер которой возвращает ListViews (другими словами, ListViews с вертикальной прокруткой, встроенные в галерею с горизонтальной прокруткой).Это вроде как работает после небольшой работы, но при попытке прокрутки по горизонтали ListView выглядит очень неустойчивым, как будто он находится в некотором залипании по центру.Я не наблюдал такого поведения ни с каким другим типом представления, встроенного в Галерею.
Вот что я попробовал:
Первоначально я обнаружил, что ListView подавляет события касания, поэтому прослушиватель жестов в Галерее никогда не запускается.
Итак, в методе onCreate() действия я создал GestureDetector:
galleryGestureDetector = new GestureDetector(this, gallery);
Затем, внутри метода getView () адаптера галереи, после того, как ListView был расширен и настроен, у меня есть некоторый код, подобный этому:
listView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
galleryGestureDetector.onTouchEvent(event);
return true;
}
});
В этом случае я даже пошел на крайний шаг, вернув true из OnTouchListener, чтобы гарантировать, что метод onTouchEvent() ListView на самом деле никогда не вызывается.Происходит то же самое нервное поведение.В результате, я думаю, я могу исключить конкурирующие реализации onTouchEvent() между двумя представлениями.
Я также попытался злоупотребить концепцией TouchDelegate, расширив сенсорный прямоугольник галереи, включив в него ListView, а затем заставив ListView делегировать ему полномочия, но и это было бесполезным усилием.
Я бы развел руками и сказал, что в настоящее время это невозможно, но приложение для социальных сетей, которое поставляется вместе с DroidX, каким-то образом выполняет эту задачу!
Решение
Проблема в том, что ListView перехватывает события касания из Галереи, а затем изменяет саму позицию просмотра.Это то, что приводит к эффекту дрожания взад-вперед, который я вижу, когда использую виджеты как есть.Я считаю это ошибкой в виджете Gallery, но в то же время ее можно исправить, создав подкласс Gallery следующим образом:
public class BetterGallery extends Gallery {
private boolean scrollingHorizontally = false;
public BetterGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public BetterGallery(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BetterGallery(Context context) {
super(context);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
return scrollingHorizontally;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
scrollingHorizontally = true;
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
scrollingHorizontally = false;
}
return super.onTouchEvent(event);
}
}
Если вы используете BetterGallery вместо Gallery, все это работает просто отлично!