整个屏幕的onTouchListener

11

我有一个屏幕上充满了按钮,但是想要使用onTouch方法来利用整个屏幕的坐标。我首先尝试使用RelativeLayout和onTouchListener,但从未成功“连接”监听器(即当触摸屏幕时不会发生任何事情),我还尝试将ImageView放在屏幕顶部,然后使此视图不可见。

最后一种方法对onClicks给出了正确的响应,但我从未成功使它不可见。

如果这是最佳解决方案,我非常怀疑,那么如何使ImageView完全不可见,而不失去其onTouchListener(我已经尝试过白色backgroundColor和setAlpha(0))。

我是否可以通过全局坐标让onTouchListener在屏幕上显示(并修改)多个按钮的同时对整个屏幕做出反应(最好不使用不可见的ImageView)?

如果您不明白我在问什么,请随时提出抱怨。我会根据需要填补空缺。

编辑:

我现在已经成功使用常规onTouch方法解决了此问题。我遇到了许多问题,使ACTION_DOWN和ACTION_MOVE都能激活按钮,但我最终使其正常工作了。对于阅读此文的其他人:可能可以使用onInterceptTouchEvent(但我从未弄清如何获取屏幕坐标而不是视图坐标)。

4个回答

8

抱歉如果我理解有误,但我认为我刚遇到了类似的问题。我想要一个标题屏幕,上面显示一张图片和一些字,比如“点击继续”之类的。我尝试了一下,发现可以让布局可点击。

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

在我的布局的xml文件中,标签用于设置背景图片(我知道您没有使用图片)。

总之,在我的活动中……

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

然后我使用switch语句来处理下一个布局中的按钮。如果需要,这里有一个链接:使用Switch语句处理按钮点击事件。似乎这种方法也适用于其他布局,并且我的主要布局上没有任何视图。(除非布局本身算作一个视图?)哈!刚刚意识到你说你已经找到了解决方案。时间真是巧啊。我会发布这篇文章,希望能帮助到某些人,祝大家编码愉快。 :)

2
如果您的目标版本高于1.6,您可以直接使用android:onClick="functionname",而无需在代码中设置focusable并分配onclick监听器。 - Yenchi

3

Dsouza我试过了,但不满意。现在我通过使用常规的onTouch方法成功解决了这个问题。我遇到了一些问题,让ACTION_DOWN和ACTION_MOVE都能激活按钮,但最终我成功了。对于其他人来说,可能可以使用onInterceptTouchEvent(但我从未弄清楚如何获取屏幕坐标而不是视图坐标)。 - keyser

3

我曾经使用dispatchTouchEvent来解决一个类似的问题。你可以把它视为onTouchEvent的即插即用替代品,除了它总是会向你发送事件,即使它在现有视图上。

如果你正在处理事件,请返回true;否则,请确保调用super.dispatchTouchEvent()并返回其结果。

至于获取屏幕坐标-只需调用MotionEvent的getRawX()getRawY()而不是getX()getY()。这些是绝对的屏幕坐标,包括操作栏和所有内容。如果你想将它们与视图进行交叉引用,getLocationOnScreen可能是最简单的解决方案。


1

触摸事件优先返回给子视图。如果您为它们定义了onClick或onTouch监听器,父视图(例如片段)将不会接收任何触摸监听器。因此,在这种情况下,如果您想要为片段定义滑动监听器,您必须在一个新的类中实现它:

    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 for fragment 和 child view 的 onClick 都运行并引起一些问题。 制作完这个类后,你必须更改你的 fragment 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();
    }

有点复杂,但完美运作:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接