Подтвердить что ты не робот

Обнаружение события касания при просмотре при перетаскивании с другого вида

Как обнаружить событие касания, если пользователь коснется представления A и перетащит его вниз на вид B. Я хочу обнаружить событие касания в представлении B.

Я добавил сенсорный прослушиватель в поле зрения B, но не получил события, если пользователь сначала коснулся A и перетащил B.

enter image description here

4b9b3361

Ответ 1

Вы можете использовать приведенный ниже код для достижения вашего запроса:

Метод проверки границ обзора (используется в коде ниже)

    Rect outRect = new Rect();
    int[] location = new int[2];

    private boolean isViewInBounds(View view, int x, int y){
        view.getDrawingRect(outRect);
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
        return outRect.contains(x, y);
    }

Тестирование с помощью двух TextView

    final TextView viewA = (TextView)  findViewById(R.id.textView);
    final TextView viewB = (TextView)  findViewById(R.id.textView2);

Настройка viewA

Пустое значение OnClickListener требуется для сохранения OnTouchListener до ACTION_UP

    viewA.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {}
    });

    viewA.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int x = (int)event.getRawX();
            int y = (int)event.getRawY();
            if(event.getAction() == MotionEvent.ACTION_UP){
                if(isViewInBounds(viewB, x, y))
                    viewB.dispatchTouchEvent(event);
                else if(isViewInBounds(viewA, x, y)){
                    Log.d(TAG, "onTouch ViewA");
                    //Here goes code to execute on onTouch ViewA
                }
            }
            // Further touch is not handled
            return false;
        }
    });

Настройка viewB

Это требуется только в том случае, если вы также хотите нажать на viewB и перетащить в viewA

    viewB.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {}
    });

    viewB.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int x = (int)event.getRawX();
            int y = (int)event.getRawY();
            if(event.getAction() == MotionEvent.ACTION_UP){
                if(isViewInBounds(viewA, x, y))
                    viewA.dispatchTouchEvent(event);
                else if(isViewInBounds(viewB, x, y)){
                    Log.d(TAG, "onTouch ViewB");
                    //Here goes code to execute on onTouch ViewB
                }
            }
            // Further touch is not handled
            return false;
        }
    });

С уважением.

Ответ 2

Я уверен, что вам нужно переопределить метод ViewGroup.dispatchTouchEvent(MotionEvent ev) в вашей ViewGroup, который содержит представления A и B. Исходная реализация определяет целевое представление, когда контейнер получает MotionEvent.getAction() == MotionEvent.ACTION_DOWN, а затем отправляет все следующие события касания к цели до получения MotionEvent.getAction() == MotionEvent.ACTION_UP или MotionEvent.ACTION_CANCEL.

В вашем случае целевым представлением является A или сам контейнер (зависит от реализации метода контейнера onInterceptTouchEvent(MotionEvent ev)). Таким образом, вы должны переопределить такое поведение и отправлять события касания не только к целевому представлению, но также ко всем представлениям, которые находятся под затронутой областью (например, для просмотра B).

Если вам интересно, вы можете поделиться образцом кода, и я постараюсь помочь вам.

Ответ 3

Если вы возвращаете true из onTouchEvent представления A, тогда событие не распространяется. В этом конкретном случае, когда A ниже B, возвращает false из onTouch вида A.

Это также поможет, если вы можете опубликовать некоторый код.

Ответ 4

В View A, переопределить onTouchEvent следующим образом:

@Override
public boolean onTouchEvent(MotionEvent event) 
{

    float x = event.getRawX();
    float y = event.getRawY();
    if ( (B.getLeft() <= x <= B.getRight()) &&
         (B.getTop() <= y <= B.getBottom())
       )
    {
        Log.i("A", "Motion Event is currently above B");
        B.dispatchTouchEvent(event);
    }

    return true;
}

В View B переопределить тот же метод, убедившись, что вернуть false:

@Override
public boolean onTouchEvent(MotionEvent event) 
{
    //TODO handle touch event
    return false;//this will allow A to continue using the event
}

Ответ 5

Попробуйте использовать фреймворк перетаскивания.

Ответ 6

Когда вы закончите просмотр B, назовите его onTouch вручную.

if (viewBRect.contains(x, y)) {
    viewBsonTouch(view, motionEvent);
}