onTouchListener для всего экрана - PullRequest
11 голосов
/ 13 апреля 2011

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

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

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

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

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

Редактировать:

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

Ответы [ 4 ]

8 голосов
/ 06 июня 2011

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

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

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

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

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

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

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

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

3 голосов
/ 17 октября 2013

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

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

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

3 голосов
/ 13 апреля 2011

Вы пробовали onInterceptTouchEvent на макете?

1 голос
/ 30 октября 2015

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

    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 после обнаружения.это важно, потому что, если мы не сделаем это несколько раз, дочерние представления могут получить событие, и оба из 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();
    }

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

...