整个屏幕的 onTouchListener

发布于 2024-11-01 04:38:11 字数 610 浏览 0 评论 0原文

我有一个充满按钮的屏幕,但希望 onTouch 方法使用整个屏幕的坐标。我首先尝试使用带有onTouchListener的RelativeLayout,但从未设法使其与侦听器“连接”(即触摸屏幕时没有任何反应),我还尝试将ImageView放在屏幕顶部,然后使该视图不可见。

最后一个方法对 onClicks 给出了正确的响应,但我从未设法使其不可见。

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

当屏幕显示(和更改)多个按钮(最好没有不可见的图像视图)时,我可以使用全局坐标使 onTouchListener 对整个屏幕做出反应吗?

如果您不明白我的要求,请随时投诉。我会尽力根据需要填补空白。

编辑:

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

I have a screen filled with buttons, but want the onTouch-method to use the entire screen's coordinates. I first tried using a RelativeLayout with an onTouchListener, but never managed to make it "connect" with the listener (i.e. nothing happened when screen was touched), I also tried putting an ImageView on top of the screen, and then making this view invisible.

This last method gave correct responses to onClicks, but I never managed to make it invisible.

If this is the best solution, which I highly doubt, how do I make the ImageView totally invisible, without losing its onTouchListener (I've experimented with white backgroundColor and setAlpha(0)).

Can I somehow make the onTouchListener react to the whole screen, using global coordinates, while the screen is showing (and altering) several buttons (preferably without the invisible imageview)?

If you don't understand what I'm asking for, feel free to complain about that. I'll try to fill the gaps as needed.

Edit:

I've now managed to resolve the issue by using the regular onTouch-method. I ran into several problems making both ACTION_DOWN and ACTION_MOVE activate the buttons, but I finally got it working. For other people reading this: onInterceptTouchEvent could possibly be used (but I never figured out how to get the screen coordinates instead of the view-coordinates).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

合久必婚 2024-11-08 04:38:11

抱歉,如果我错了,但我相信我也遇到过类似的问题。我想要一个标题屏幕,显示一张图片,并在图片上写着“点击继续”或类似的文字。我搞乱了一会儿,发现你可以使布局可点击。

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

位于我的布局的 xml 文件中。背景图像只是在背景属性中(我意识到您没有使用图像)

无论如何,回到我的活动中

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

然后我使用 switch 语句来处理它以及下一个布局上的按钮。在这里,如果您需要它:使用 Switch 语句来处理按钮点击

似乎这也应该适用于其他布局,而且我对我的主布局实际上没有任何视图。 (除非布局本身算作一个?)

哈!刚刚意识到你说你找到了解决方案。愚蠢的时机。如果有机会这对某人有帮助,我会发帖,祝大家编码愉快。 :)

Sorry if I'm wrong, but I believe I've just had a similar problem. I wanted a title screen that displayed a picture and on the picture words that say "Click to go on" or something similar. I messed around for a bit and found that you can make a layout clickable.

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

is in my xml file for my layout. The background image is simply in the background attribute (I realize you aren't using images)

Anyway, back in my activity

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

And then I use a switch statement to handle that and the buttons that are on the next layout. Here if you need it: Using Switch Statement to Handle Button Clicks

Seems this should work with other layouts as well, and I don't have literally any views on my main layout. (unless the layout itself counts as one?)

Ha! Just realized you said you found the solution. Silly timing. I'll post on the off-chance this helps someone, happy coding everyone. :)

街角迷惘 2024-11-08 04:38:11

您是否尝试过 onInterceptTouchEvent布局?

Have you tried onInterceptTouchEvent on the layout?

烙印 2024-11-08 04:38:11

我使用 dispatchTouchEvent 作为类似的问题。您可以将其视为 onTouchEvent 的直接替代品,只不过它总是向您发送事件,即使该事件是在现有视图上进行的。

如果您正在处理该事件,则返回 true,否则,请务必调用 super.dispatchTouchEvent() 并返回其结果。

至于获取屏幕坐标 - 只需调用 MotionEvent 的 getRawX()getRawY() 而不是 getX()getY()。这些是绝对屏幕坐标,包括操作栏等。如果您想交叉引用那些具有视图的视图,getLocationOnScreen 可能是最简单的解决方案。

I used dispatchTouchEvent for a similar problem. You could consider it a drop-in replacement for onTouchEvent, except that it always sends you an event, even if it's over an existing view.

Return true if you're handling the event, otherwise, be sure to call super.dispatchTouchEvent() and return its result.

As for getting screen coordinates - simply call the MotionEvent's getRawX() and getRawY() rather than getX() and getY(). Those are the absolute screen coordinates, including the action bar and all. If you want to cross-reference those with views, getLocationOnScreen is probably the easiest solution.

千と千尋 2024-11-08 04:38:11

触摸事件首先返回到子视图。如果您为它们定义 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 和子视图的 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();
    }

有点复杂,但效果很完美:)

touch event return's to child views first. and if you define onClick or onTouch listener for them, parnt view (for example fragment) will not receive any touch listener. So if you want define swipe listener for fragment in this situation, you must implement it in a new class:

    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;
    }
}

you can make implements for other types of Layouts completely like this. this class can detect both right and left swipe and specially it returns onInterceptTouchEvent true after detect. its important because if we don't do it some times child views maybe receive event and both of Swipe for fragment and onClick for child view (for example) runs and cause some issues.
after making this class, you must change your fragment xml file:

    <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>

you see that begin tag is the class that we made. now in fragment class:

            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();
    }

It's a little complicated but works perfect :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文