Проблема с обнаружением жестов над ListView

У меня есть Activity, который содержит ViewFlipper. ViewFlipper включает в себя 2 макета, оба из которых по сути являются только ListViews.

Итак, идея здесь в том, что у меня есть два списка, и для перехода от одного к другому я использую горизонтальное прокручивание.

У меня это работает. Однако, какой бы элемент списка ни был на вашем пальце при запуске салфетки, этот элемент также будет длинным щелчком.

Вот соответствующий код, который у меня есть:

public class MyActivity extends Activity implements OnItemClickListener, OnClickListener { private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private GestureDetector mGestureDetector; View.OnTouchListener mGestureListener; class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { if (mCurrentScreen != SCREEN_SECONDLIST) { mCurrentScreen = SCREEN_SECONDLIST; mFlipper.setInAnimation(inFromRightAnimation()); mFlipper.setOutAnimation(outToLeftAnimation()); mFlipper.showNext(); updateNavigationBar(); } } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { if (mCurrentScreen != SCREEN_FIRSTLIST) { mCurrentScreen = SCREEN_FIRSTLIST; mFlipper.setInAnimation(inFromLeftAnimation()); mFlipper.setOutAnimation(outToRightAnimation()); mFlipper.showPrevious(); updateNavigationBar(); } } } catch (Exception e) { // nothing } return true; } } @Override public boolean onTouchEvent(MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) return true; else return false; } ViewFlipper mFlipper; private int mCurrentScreen = SCREEN_FIRSTLIST; private ListView mList1; private ListView mList2; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.layout_flipper); mFlipper = (ViewFlipper) findViewById(R.id.flipper); mGestureDetector = new GestureDetector(new MyGestureDetector()); mGestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } return false; } }; // set up List1 screen mList1List = (ListView)findViewById(R.id.list1); mList1List.setOnItemClickListener(this); mList1List.setOnTouchListener(mGestureListener); // set up List2 screen mList2List = (ListView)findViewById(R.id.list2); mList2List.setOnItemClickListener(this); mList2List.setOnTouchListener(mGestureListener); } … } 

Если я изменю «return true»; Оператора GestureDetector, чтобы «вернуть false», я не получаю длинные клики. К сожалению, я получаю регулярные клики.

Кто-нибудь знает, как я могу обойти это?

Просто совсем другой ответ, совершенно другой подход …

Я сделал собственное представление под названием SwipeView, это открытый исходный код и т. Д. И т. Д. Бла-бла-бла. Он должен позволить вам делать то, что вы хотите сделать, так же просто, как и вы:

 mSwipeView.addChild(myList1); mSwipeView.addChild(myList2); 

Вам не придется возиться с детекторами жестов или чем-то еще, и салфетки должны следовать за вашим пальцем, как вы это делаете …

(Это читается как ужасное ужасное объявление, пожалуйста, извините меня. Это был долгий день;)

Есть несколько замечательных ссылок:

http://jasonfry.co.uk/?id=23

http://jasonfry.co.uk/?id=24

http://jasonfry.co.uk/?id=28

Поскольку вы используете GestureDetector , нужно выполнить реализацию SimpleGestureDetector.onLongPress(MotionEvent e) для обработки длинных кликов. Тем не менее, вы не можете знать список, который был долго нажат оттуда, поэтому вам нужно запомнить его из обычного onItemLongClick() .

 class MyGestureDetector extends SimpleOnGestureListener { ... @Override public void onLongPress(MotionEvent e) { if (longClickedItem != -1) { Toast.makeText(MainActivity.this, "Long click!", Toast.LENGTH_LONG).show(); } } } int longClickedItem = -1; @Override public boolean onItemLongClick(AdapterView<?> list, View view, int position, long id) { longClickedItem = position; return true; } @Override public boolean onTouchEvent(MotionEvent event) { // Reset longclick item if new touch is starting if (event.getAction()==MotionEvent.ACTION_DOWN) { longClickedItem = -1; } if (mGestureDetector.onTouchEvent(event)) return true; else return false; } 

Я тестировал это, и он работает нормально.

Идите к вашему жестомДетектор и установите

  mGestureDetector.setIsLongpressEnabled(false); 

Это предотвратит обнаружение длинных событий.

[РЕДАКТИРОВАТЬ] Поцарапайте это, совершенно неправильно.

Я думаю, вам нужно будет обновить эту часть и определить, прокручивались ли вы влево или вправо и возвращаете true, если вы находитесь в состоянии подкачки. Или, по крайней мере, это то, где я буду смотреть первым.

  mGestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (mGestureDetector.onTouchEvent(event)) { return true; } return false; } }; 

Продолжая с моим бедным примером, извините.

Внутри onTouch я считаю, что вы можете проверить event.getAction () и определить, произошел ли длинный клик. Если оно есть, и ваше движение в движении, то верните true, чтобы зафиксировать длинный клик.

Боитесь, что это скорее предложение, чем окончательный ответ.

Также вы проверяете другую на [методы], которую вы можете переопределить из SimpleOnGestureListener. Только что проверили и

 @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub super.onLongPress(e); } 

Возможно, вы можете экспериментировать.

Я разработал пользовательский компонент, полученный из horizontalScrollView, который делает это. У меня есть listViews как вид ребенка и проведите пальцем без длинного нажатия. Он поддерживает списокAdapter, который может быть любым, что вы хотите (ArrayAdapter, CursorAdapter …). Он загружает до трех дочерних представлений, а затем переворачивает, просто свопит их по обе стороны. Большая часть из них отличается от ListView и нуждается в рефакторинге. Его путь слишком длинный, чтобы публиковать здесь напрямую.

http://pastie.org/1480091

Удалите getListView().setOnItemLongClickListener

Добавить в свой класс MyGestureDetector :

 public void onLongPress(MotionEvent e) { final int position = getListView().pointToPosition((int) e.getX(), (int) e.getY()); // what you want do super.onLongPress(e); }