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 для обращения к кнопкам кликов
Похоже, это должно работать и с другими макетами, и у меня нет буквально каких-либо взглядов на мой основной макет. (если только сама компоновка не считается одной?)
Ха! Просто понял, что сказал, что нашел решение. Глупое время. Я опубликую на случай, что это помогает кому-то, счастлив кодировать всех.:)
Ответ 2
Вы пробовали onInterceptTouchEvent на макете?
Ответ 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();
}
Это немного сложно, но отлично работает:)