Глядя на стену (GridView?), Которая выходит за пределы экрана, и пользователь может коснуться ее, чтобы переместить ее

Желаемый эффект У меня есть куча маленьких изображений, которые я хотел бы показать на «стене», а затем позволить пользователю выбрасывать эту стену в любом направлении и выбирать изображение.

Первоначальная идея как возможная реализация Я думал о GridView, который больше, чем может показать экран, но все примеры использования этого виджета показывают, что Галерея не выходит за пределы размера экрана.

Вопрос: Каков лучший виджет для использования желаемого эффекта? Образец кода будет особенно полезен.

EDIT … если у кого-то есть пример кода, который позволит мне разместить около 30 изображений на «стене» (таблица будет хорошей), тогда я буду принимать это как ответ. Обратите внимание, что «стена» должна выглядеть так, как будто она выходит за пределы экрана и позволяет пользователю использовать палец для перетаскивания «стены» вверх по левому краю. Перетаскивание должно быть в режиме «свободной формы». Один щелчок на изображении выбирает его, и обратный вызов должен быть обнаружен. Я создал щедрость для этого решения.

Solutions Collecting From Web of "Глядя на стену (GridView?), Которая выходит за пределы экрана, и пользователь может коснуться ее, чтобы переместить ее"

Решение на самом деле довольно простое, но боль. Я должен был реализовать именно это в рамках программы, которую я недавно сделал. Однако есть несколько сложных вещей, которые вам нужно преодолеть. Следует отметить, что разные версии ОС имеют разные впечатления. Этот метод иногда оказывает неблагоприятное влияние на определенную специализацию или кладку, чтобы сделать эту работу как рисунок. Хотя у меня есть рабочая копия, код, который я предоставляю, не для всех и зависит от любых других изменений или настроек в вашем коде.

  • Set android:layout_width to wrap_content
  • Set android:layout_height to wrap_content
  • В вашем коде:
    • Определите, сколько строк у вас будет.
    • Разделите количество элементов на количество строк.
    • Добавьте gridView. setStretchMode(NO_STRETCH);
    • Добавьте gridView. setNumColumns( количество столбцов );
    • Добавьте gridView. setColumnWidth( явная ширина в пикселях );
  • Прокручивать:
    • Вы можете просто использовать gridView. scrollBy() в вашем onTouchEvent()

Это шаги. Все они необходимы, чтобы заставить его работать. Ключ представляет собой NO_STRETCH с явным количеством столбцов с определенной шириной. Если вам требуется уточнение, можно предоставить дополнительную информацию. Вы можете даже использовать VelocityTracker или onFling для обработки flinging. У меня есть snappingToPage включен в мой. Используя это решение, даже не требуется переопределять onDraw() или onLayout() . Эти три строки кода избавляются от необходимости использования WebView или любого другого встраивания или вложения.

Двунаправленная прокрутка также довольно проста в применении. Вот простое решение для кода:

  1. Во-первых, в вашем классе начните отслеживать позиции X и Y, создав двух членов класса. Также добавьте отслеживание состояния;

     // Holds the last position of the touch event (including movement) int myLastX; int myLastY; // Tracks the state of the Touch handling final static private int TOUCH_STATE_REST = 0; final static private int TOUCH_STATE_SCROLLING = 1; int myState = TOUCH_STATE_REST; 
  2. Во-вторых, убедитесь, что вы проверяете прокрутку, таким образом вы все равно можете щелкнуть или долго щелкнуть изображения самостоятельно.

     @Override public boolean onInterceptTouchEvent(final MotionEvent ev) {//User is already scrolling something. If we haven't interrupted this already, // then something else is handling its own scrolling and we should let this be. // Once we return TRUE, this event no longer fires and instead all goes to // onTouch() until the next TouchEvent begins (often beginning with ACTION_DOWN). if ((ev.getAction() == MotionEvent.ACTION_MOVE) && (myState != TOUCH_STATE_REST)) return false; // Grab the X and Y positions of the MotionEvent final float _x = ev.getX(); final float _y = ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: final int _diffX = (int) Math.abs(_x - myLastX); final int _diffY = (int) Math.abs(_y - myLastY); final boolean xMoved = _diffX > 0; final boolean yMoved = _diffY > 0; if (xMoved || yMoved) myState = TOUCH_STATE_SCROLLING; break; case MotionEvent.ACTION_DOWN: // Remember location of down touch myLastX = _x; myLastY = _y; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (myState == TOUCH_STATE_SCROLLING) // Release the drag myState = TOUCH_STATE_REST; } //If we are not At Rest, start handling in our own onTouch() return myState != TOUCH_STATE_REST; } 
  3. После того, как GridView знает, что вы прокручиваете, он отправит все сенсорные события в onTouch. Сделайте свою прокрутку здесь.

     @Override public boolean onTouchEvent(final MotionEvent ev) { final int action = ev.getAction(); final float x = ev.getX(); final float y = ev.getY(); final View child; switch (action) { case MotionEvent.ACTION_DOWN: //Supplemental code, if needed break; case MotionEvent.ACTION_MOVE: // This handles Scrolling only. if (myState == TOUCH_STATE_SCROLLING) { // Scroll to follow the motion event // This will update the vars as long as your finger is down. final int deltaX = (int) (myLastX - x); final int deltaY = (int) (myLastY - y); myLastX = x; myLastY = y; scrollBy(deltaX, deltaY); } break; case MotionEvent.ACTION_UP: // If Scrolling, stop the scroll so we can scroll later. if (myState == TOUCH_STATE_SCROLLING) myState = TOUCH_STATE_REST; break case MotionEvent.ACTION_CANCEL: // This is just a failsafe. I don't even know how to cancel a touch event myState = TOUCH_STATE_REST; } return true; } 

Если курс, это решение перемещается одновременно на X и Y. Если вы хотите перемещать только одно направление за раз, вы можете легко отличить, проверив большую разницу X и Y. ( Math.abs(deltaX) > Math.abs(deltaY) ) Ниже представлен частичный образец для одной направленной прокрутки, но он может переключаться между X или Y.

3b. Измените это в своем OnTouch() если вы хотите обрабатывать одно направление за раз:

  case MotionEvent.ACTION_MOVE: if (myState == TOUCH_STATE_SCROLLING) { //This will update the vars as long as your finger is down. final int deltaX = (int) (myLastX - x); final int deltaY = (int) (myLastY - y); myLastX = x; myLastY = y; // Check which direction is the bigger of the two if (Math.abs(deltaX) > Math.abs(deltaY)) scrollBy(deltaX, 0); else if (Math.abs(deltaY) > Math.abs(deltaX)) scrollBy(0, deltaY); // We do nothing if they are equal. } break; 

FuzzicalLogic

GridView может иметь контент, который выходит за пределы размера экрана, но только в вертикальном направлении.

Вопрос: Каков наилучший виджет для реализации желаемого эффекта?
Не являются виджетами по умолчанию (по крайней мере до 3.0), которые реализуют 2D-прокрутку. Все они реализуют только 1D (прокрутка в одном направлении). К сожалению, решение вашей проблемы не так просто.

Ты мог:

  • Поместите TableLayout внутри пользовательского класса ScrollView и обработайте события касания самостоятельно. Это позволит вам сделать правильное 2D-панорамирование, но не будет так хорош для больших наборов данных, поскольку не будет никакой утилизации просмотра
  • Измените GridView если возможно, чтобы включить функцию горизонтальной прокрутки (возможно, лучшее решение, если вы можете это сделать)
  • Попробуйте помещать TableLayout внутри ScrollViewlayout_width="wrap_content ), который вы помещаете в HorizontalScrollView – хотя это может работать, это не было бы оптимальным решением
  • Сделайте что-нибудь с OpenGL и нарисуйте прямо на холсте – так как приложение Gallery Gallery по умолчанию делает это «стена картин»,

Я думаю, что единственное решение для Android для Android – это иметь встроенный WebView, в котором вы можете иметь этот двумерный свиток (и, кстати, это единственное, что имеет эту возможность).

Нажимайте изображение, которое вы можете контролировать по обращению от JavaScript к JAva.

Это не очень «красиво», но … это единственный жизнеспособный способ сделать то, что вы хотите «из коробки».

Я реализовал GridView который переопределяет методы onInterceptTouchEvent . Я установил OnTouchListener как объяснил Fuzzical Logic . Моя проблема в том, что установка пользовательского OnTouchListener, объекты моего gridView больше не доступны для кликов. Это потому, что по умолчанию OnTouchListener из GridView вызывает onItemClickListener?

Я хотел бы иметь прокручиваемый GridView 2 направления, но у него все еще есть cliackable объекты. Должен ли я реализовать свой собственный метод, чтобы проверить, соответствует ли касание элементу или есть ли более простой способ достичь этого?

Grodak