Передача событий касания к родительскому виду
У меня есть пользовательский ViewSwitcher
, в котором я реализовал сенсорные события, поэтому я
я могу прокручивать экраны с помощью сенсорного экрана.
Моя иерархия раскладки выглядит следующим образом:
<ViewSwitcher>
<LinearLayout>
<ListView />
</LinearLayout>
<LinearLayout>
<ListView />
</LinearLayout>
</ViewSwitcher>
Теперь проблема заключается в том, что события касания потребляются
ListViews
, и я не могу переключать представления. Он отлично работает, когда я
не имеют ListViews
. Мне нужно прокрутить
просмотрите и прокрутите ListView
.
Как это решить?
EDIT. Мне также нужны элементы ListView
, которые можно щелкнуть.
Спасибо заранее!
Ответы
Ответ 1
Спасибо всем за ответ на вопрос. Но мне удалось понять это гораздо проще. Поскольку мой ViewSwitcher
не обнаруживал событие касания, я перехватил событие touch, получившее название onTouchEvent()
и возвращенный false
. Здесь:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
onTouchEvent(ev);
return false;
}
Переопределив onInterceptTouchEvent()
, я смог перехватить событие касания в активности. Затем я назвал onTouchEvent()
в ViewSwitcher
, который обрабатывает переключение ListViews
. И, наконец, возвращая false
, он гарантирует, что ViewGroup
не использует событие.
Ответ 2
Самый простой способ передать дочерний вид TouchEvent в родительский вид - это добавить его в дочерний режим:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
return false;
}
Ответ 3
Я не думаю, что для вас есть простой способ сделать это.
Это не так сложно, но вам нужно будет создать собственное представление, расширяющее ListView. Затем вы можете переопределить обработчик onTouch
и решить (в зависимости от события касания), хотите ли вы обработать его (и вернуть true) или передать его в родительский вид.
Проблема также в том, что когда View обрабатывает событие touch, это тот, который получит все остальные...
Из Документация для Android:
onTouch() - возвращает логическое значение укажите, является ли ваш слушатель потребляет это событие. Важный дело в том, что это событие может иметь несколько действий, следующих за каждым Другие. Итак, если вы вернете false, когда событие с нисходящим действием, вы укажите, что вы не потребляли события, а также не заинтересованы в последующих действиях с этого события. Таким образом, вы не будете другие действия в рамках мероприятия, такие как жест пальца, или возможный событие действия
Итак, например, если вы хотите, чтобы вертикальный ход прокручивался по списку и во время одного и того же события касания (без поднятия пальца), вы хотите, чтобы горизонтальное перемещение переключало виды, что будет довольно сложным.
Но если вы можете использовать жесты, например, или обрабатывать все в своем пользовательском представлении и в зависимости от того, что такое MotionEvent, отправьте команды в ViewSwitcher.
Ответ 4
Пробовал ли вы настраивать элементы ListView так же, как и без кликов: listView.setClickable(false); Это должно инициировать событие click вверх.
Ответ 5
Если ваше представление хочет передать событие, убедитесь, что вы вернули false в onTouchEvent. В противном случае платформа считает, что вы потребляете событие, и дальнейшая обработка не требуется.
Ответ 6
я сделал, чтобы установить touchheventlistener в listview в viewswitcher, обрабатывает событие, обнаруживает действие fling и вызывает metchod viewswitcher. он работает.
Ответ 7
Вы также можете вставить вызов для обработки 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;
}
Ответ 8
В моем родительском макете единственный способ, которым я нашел, чтобы ребенок не мог захватить событие касания, - это переопределить onInterceptTouchEvent, чтобы вернуть true.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
return true;
}
Ответ 9
Необходимо было обработать прикосновение в 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;
}
};