Передача событий касания к родительскому виду

У меня есть пользовательский ViewSwitcher в котором я реализовал сенсорные события, поэтому я могу прокручивать экраны с помощью сенсорного экрана.

Моя иерархия макетов выглядит так:

 <ViewSwitcher> <LinearLayout> <ListView /> </LinearLayout> <LinearLayout> <ListView /> </LinearLayout> </ViewSwitcher> 

Теперь проблема заключается в том, что события касания используются ListViews и я не могу переключать представления. Он отлично работает, когда у меня нет ListViews . Мне нужно прокручивать просмотры и прокручивать ListView .

Как я могу это решить?

EDIT : Мне также нужно, чтобы элементы ListView могли быть интерактивными.

Заранее спасибо!

Solutions Collecting From Web of "Передача событий касания к родительскому виду"

Спасибо всем, кто ответил на вопрос. Но мне удалось понять это намного проще. Поскольку мой ViewSwitcher не обнаруживал событие касания, я перехватил событие touch, называемое onTouchEvent() и возвратил false . Вот:

 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { onTouchEvent(ev); return false; } 

Переопределяя onInterceptTouchEvent() , я смог перехватить событие касания в активности. Затем я вызвал onTouchEvent() в ViewSwitcher который обрабатывает переключение ListViews . И, наконец, возвращая false , он гарантирует, что ViewGroup не использует событие.

Самый простой способ передать представление TouchEvent для дочернего представления в родительский вид – это добавить его в дочерний режим:

 @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); return false; } 

Я не думаю, что для вас есть простой способ сделать это.

Это не так сложно, но вам нужно будет создать собственное представление, расширяющее ListView. Затем вы можете переопределить обработчик onTouch и решить (в зависимости от события касания), хотите ли вы обработать его (и вернуть true) или передать его родительскому представлению.

Проблема также в том, что когда View обрабатывает событие touch, это тот, который получит все остальные …

Из документации для Android :

OnTouch () – возвращает логическое значение, указывающее, использует ли ваш слушатель это событие. Важно то, что это событие может иметь несколько действий, которые следуют друг за другом. Таким образом, если вы вернете false при поступлении события вниз, вы указываете, что вы не использовали это событие, а также не заинтересованы в последующих действиях этого события. Таким образом, вы не будете называться для каких-либо других действий внутри события, таких как жест пальца или возможное событие действия

Так, например, если вы хотите иметь вертикальное перемещение для прокрутки списка и во время одного и того же события касания (без поднятия пальца), вы хотите, чтобы горизонтальное перемещение переключало виды, это будет довольно сложно.

Но если вы можете использовать жесты, например, или обрабатывать все в своем пользовательском представлении и в зависимости от того, что такое MotionEvent, отправьте команды в ViewSwitcher.

Вы пытались настроить элементы ListView как неаккуратные следующим образом: listView.setClickable (false); Это должно стимулировать событие щелчка вверх.

Если ваше представление хочет передать событие, убедитесь, что вы вернули false в onTouchEvent. В противном случае платформа думает, что вы потребляете событие, и дальнейшая обработка не требуется.

Я сделал, чтобы установить touchheventlistener в listview в viewswitcher, обрабатывает событие, обнаруживает действие fling и вызывает metchod viewswitcher. оно работает.

Вы также можете вставить вызов для обработки touchevent в dispatchTouchEvent , но в этом случае вы также должны переопределить onTouchEvent для возврата true, иначе будет передан только первый MotionEvent DOWN этого жеста.

Это осязаемый контейнер-контейнер:

 <?xml version="1.0" encoding="utf-8"?> <view xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" class="com.example.myapp.FragmentContainer$TouchableWrapper" /> 

И класс:

 public static class TouchableWrapper extends FrameLayout { private GestureDetector gestureDetector; public void setGestureDetector(GestureDetector gestureDetector) { this.gestureDetector = gestureDetector; } // these constructors for the XML inflater public TouchableWrapper(Context context) { super(context); } public TouchableWrapper(Context context, AttributeSet attrs) { super(context, attrs); } public TouchableWrapper(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { Log.d(TAG, "onInterceptTouchEvent " + event.toString()); return false; // true for intercept, false è default and pass on to children View } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.d(TAG, "dispatchTouchEvent " + event.toString()); gestureDetector.onTouchEvent(event); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG, "onTouchEvent " + event.toString()); return true; //return super.onTouchEvent(event); } } 

Это ссылка GestureDetector :

 private GestureDetector gestureDetector; 

Это GestureListener :

 private GestureDetector.SimpleOnGestureListener sOGL = new GestureDetector.SimpleOnGestureListener() { private static final int SWIPE_THRESHOLD = 100; private static final int SWIPE_VELOCITY_THRESHOLD = 100; @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { boolean result = false; try { float diffY = e2.getY() - e1.getY(); float diffX = e2.getX() - e1.getX(); if (Math.abs(diffX) > Math.abs(diffY)) { if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { if (diffX > 0) { goToRight(); // onSwipeRight(); } else { goToLeft(); // onSwipeLeft(); } } result = true; } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) { if (diffY > 0) { // onSwipeBottom(); } else { // onSwipeTop(); } } result = true; } catch (Exception exception) { exception.printStackTrace(); } return result; // return false indicate event not handled } }; 

Ant это для загрузки осязаемого фрагмента контейнера и содержащегося фрагмента:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView()"); View view = inflater.inflate(R.layout.fragmentcontainer, container, false); gestureDetector = new GestureDetector(view.getContext(), sOGL); ((FragmentContainer.TouchableWrapper) view).setGestureDetector(gestureDetector); FragmentManager fm = this.getFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.pager, frag).commit(); return view; } 

В моем родительском макете единственный способ, которым я нашел, чтобы ребенок не мог захватить событие касания, – это переопределить onInterceptTouchEvent, чтобы вернуть true.

 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; } 

Необходимо было обработать прикосновение в TextView в родительском представлении с autoLink = "three". Так получилось:

 private LinearLayout mParentView; private TextView mTextView; private View.OnTouchListener mParentListener = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { ...... return false; } }; mParentView.setOnTouchListener(mParentListener); mTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mParentListener.onTouch(mParentView, event); return false; } };