OnTouchListener для всего экрана

У меня есть экран, заполненный кнопками, но вы хотите, чтобы метод onTouch использовал все координаты экрана. Я сначала попытался использовать RelativeLayout с onTouchListener, но так и не смог заставить его "подключиться" к слушателю (т.е. Ничего не происходило, когда экран был затронут), я также попытался помещать ImageView поверх экрана, а затем сделать это представление невидимым.

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

Если это лучшее решение, которое я очень сомневаюсь, как сделать ImageView полностью невидимым, не теряя его onTouchListener (я экспериментировал с белым фономColor и setAlpha (0)).

Можно ли как-то заставить onTouchListener реагировать на весь экран, используя глобальные координаты, в то время как на экране отображаются (и изменяются) несколько кнопок (желательно без невидимого изображения)?

Если вы не понимаете, о чем я прошу, не стесняйтесь об этом. Я постараюсь заполнить пробелы по мере необходимости.

Edit:

Теперь мне удалось решить проблему, используя обычный метод onTouch. Я столкнулся с несколькими проблемами, так как ACTION_DOWN и ACTION_MOVE активировали кнопки, но я, наконец, начал работать. Для других людей, читающих это: onInterceptTouchEvent можно было бы использовать (но я никогда не выяснял, как получить координаты экрана вместо координат вида).

Ответ 1

Извините, если я ошибаюсь, но я считаю, что у меня была аналогичная проблема. Мне нужен экран заголовка, на котором была изображена фотография, а также на словах с изображением "Нажмите, чтобы продолжить" или что-то подобное. Я немного испортился и обнаружил, что вы можете сделать доступный макет.

    android:focusable="true" 
    android:id="@+id/titlescreenframe">

находится в моем XML файле для моего макета. Фоновое изображение просто находится в фоновом атрибуте (я понимаю, что вы не используете изображения)

В любом случае, назад в моей деятельности

    private FrameLayout fl;
    ...
    fl = (FrameLayout)findViewById(R.id.titlescreenframe);
    fl.setOnClickListener(this);

И затем я использую оператор switch для его обработки и кнопки, которые находятся на следующем макете. Здесь, если вам это нужно: Использование оператора switch для обращения к кнопкам кликов

Похоже, это должно работать и с другими макетами, и у меня нет буквально каких-либо взглядов на мой основной макет. (если только сама компоновка не считается одной?)

Ха! Просто понял, что сказал, что нашел решение. Глупое время. Я опубликую на случай, что это помогает кому-то, счастлив кодировать всех.:)

Ответ 3

Я использовал dispatchTouchEvent для аналогичной проблемы. Вы можете рассмотреть возможность замены на onTouchEvent, за исключением того, что он всегда отправляет вам событие, даже если оно находится поверх существующего представления.

Возвращаем true, если вы обрабатываете событие, в противном случае обязательно вызывайте super.dispatchTouchEvent() и возвращайте его результат.

Как получить координаты экрана - просто вызовите MotionEvent getRawX() и getRawY(), а не getX() и getY(). Это абсолютные координаты экрана, включая панель действий и все. Если вы хотите перекрестно ссылаться на те, у которых есть представления, getLocationOnScreen, вероятно, является самым простым решением.

Ответ 4

Прикоснитесь к событию возврата к дочерним представлениям. и если вы определяете для них onClick или onTouch, представление parnt (например, фрагмент) не получит никакого прослушивателя прикосновений. Поэтому, если вы хотите определить swipe-прослушиватель для фрагмента в этой ситуации, вы должны реализовать его в новом классе:

    package com.neganet.QRelations.fragments;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

public class SwipeListenerFragment extends FrameLayout {
    private float x1,x2;
    static final int MIN_DISTANCE=150;
    private onSwipeEventDetected mSwipeDetectedListener;


    public SwipeListenerFragment(Context context) {
        super(context);
    }

    public SwipeListenerFragment(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SwipeListenerFragment(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean result=false;
        switch(ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                x1 = ev.getX();
                break;
            case MotionEvent.ACTION_UP:
                x2 = ev.getX();
                float deltaX = x2 - x1;
                if (Math.abs(deltaX) > MIN_DISTANCE)
                {
                    if(deltaX<0)
                    {
                        result=true;
                        if(mSwipeDetectedListener!=null)
                            mSwipeDetectedListener.swipeLeftDetected();

                    }else if(deltaX>0){
                        result=true;
                        if(mSwipeDetectedListener!=null)
                            mSwipeDetectedListener.swipeRightDetected();
                    }
                }
                break;
        }
        return result;
    }

    public interface onSwipeEventDetected
    {
        public void swipeLeftDetected();
        public void swipeRightDetected();

    }

    public void registerToSwipeEvents(onSwipeEventDetected listener)
    {
        this.mSwipeDetectedListener=listener;
    }
}

вы можете полностью реализовать инструменты для других типов макетов. этот класс может обнаруживать как правый, так и левый салфетки и особенно он возвращает onInterceptTouchEvent true после обнаружения. это важно, потому что, если мы этого не сделаем, некоторые представления child могут получать событие, а оба - для Swipe для фрагмента и onClick для просмотра дочерних элементов (например) и вызывают некоторые проблемы. после создания этого класса вы должны изменить файл xml-фрагмента:

    <com.neganet.QRelations.fragments.SwipeListenerFragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:id="@+id/main_list_layout"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:layout_height="match_parent" tools:context="com.neganet.QRelations.fragments.mainList"
    android:background="@color/main_frag_back">

    <!-- TODO: Update blank fragment layout -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/farazList"
        android:scrollbars="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="left|center_vertical" />
</com.neganet.QRelations.fragments.SwipeListenerFragment>

вы видите, что начальный тег - это класс, который мы создали. теперь в классе фрагмента:

            View view=inflater.inflate(R.layout.fragment_main_list, container, false);
        SwipeListenerFragment tdView=(SwipeListenerFragment) view;
        tdView.registerToSwipeEvents(this);


and then Implement SwipeListenerFragment.onSwipeEventDetected in it:

        @Override
    public void swipeLeftDetected() {
        Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void swipeRightDetected() {
        Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
    }

Это немного сложно, но отлично работает:)