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

У меня есть пользовательский 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;
    }
};