Передача сенсорных событий в родительский вид - PullRequest
34 голосов
/ 16 июня 2011

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

Моя иерархия макетов выглядит следующим образом:

<ViewSwitcher>

    <LinearLayout>
        <ListView />
    </LinearLayout>

    <LinearLayout>
        <ListView />
    </LinearLayout>

</ViewSwitcher>

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

Как мне решить эту проблему?

РЕДАКТИРОВАТЬ : Мне также нужно, чтобы элементы ListView были активными.

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

Ответы [ 9 ]

79 голосов
/ 17 июня 2011

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

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

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

8 голосов
/ 03 сентября 2014

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

@Override
public boolean onTouchEvent(MotionEvent event) { 
    super.onTouchEvent(event);
    return false;
}
2 голосов
/ 10 мая 2017

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

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    return true;
}
1 голос
/ 16 июня 2011

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

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

Проблема также в том, что, как только представление обрабатывает сенсорное событие, оно получает все оставшиеся ...

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

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

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

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

0 голосов
/ 30 мая 2017

Необходимо было обработать касание в 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;
    }
};
0 голосов
/ 06 августа 2015

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

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

<?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;
}
0 голосов
/ 23 апреля 2013

Что я сделал, так это установил toucheventlistener на просмотр списка в viewwitcher, обработал событие, обнаружил действие броска и вызвал метчод viewswitcher. это работает.

0 голосов
/ 16 июня 2011

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

0 голосов
/ 16 июня 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...