触摸事件、点击事件和长按事件的调用

12

我们的应用程序中,我们使用按钮处理事件来记录数据。

最初,当我同时使用setOnLongClickListener()setOnClickListener()来处理同一个按钮时,它对我们很好用。

这意味着它会基于按钮的单击和长按调用这两个监听器。现在,当我尝试在相同的按钮上使用setOnTouchListener(),并结合setOnLongClickListener()setOnClickListener()使用时,只有OnTouch事件有效,其余的onclick和onLongclick事件都不起作用。

有人能告诉我为什么会出现这种情况,并且如果可能,用示例解释一下吗?

我使用的代码:

Button btnAdd=new Button(this)

btnAdd.setOnLongClickListener(this);

btnAdd.setOnClickListener(this);

btnAdd.setOnTouchClickListener(this);

public void onClick(View v)
{
    //Statements;
}

public void onLongClick(View v)
{
    //Statements;
}

public boolean onTouch(View v, MotionEvent e) 
{
    switch (e.getAction())
    {
        case MotionEvent.ACTION_DOWN:
        {
            //store the X value when the user's finger was pressed down
            m_downXValue = e.getX();
            break;
        }   
        
        case MotionEvent.ACTION_UP:
        {
            //Get the X value when the user released his/her finger
            float currentX = e.getX();              
            //MotionEvent x=MotionEvent.obtain((long) m_downXValue,  SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 1, 1, 1, 1,0, 0, 0, 0, 0);
 
            // going forwards: pushing stuff to the left
            if (m_downXValue > currentX && currentX < 0)
            {                   
                ViewFlipper vf = (ViewFlipper) findViewById(R.id.flipview);
                vf.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_left));
                
               
                vf.showNext();
                               
            }
            
            // going backwards: pushing stuff to the right
            if (m_downXValue < currentX && currentX > 100)
            {                   
                ViewFlipper vf = (ViewFlipper) findViewById(R.id.flipview);                                     
                vf.setAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_right));
                
                
                vf.showPrevious();
                                  
            }   
            
            if (m_downXValue == currentX)
            {                   
                onClick(v);
            }    
         
            break;
        }
    }
    return true;
}

嗨,Lukas,你能帮我解决这个问题吗? - AndroidDev
在调用onTouch时,您是否考虑MotionEvent? - Dyonisos
我刚刚编辑了onTouch事件的代码。我找到了调用onClick事件的提示..但是如何调用onLongClick事件呢..请帮帮我。 - AndroidDev
嘿Dyonisos,你看过修改后的代码了吗? - AndroidDev
6个回答

25
根据处理UI事件文档:
- onLongClick() - 这返回一个布尔值,用于指示您是否已消耗事件且不应进一步进行。也就是说,如果您已处理事件并希望停止在此处,请返回true;如果您没有处理它和/或事件应继续到任何其他on-click监听器,则返回false。
另外,关于onTouch:
- onTouch() - 这返回一个布尔值,用于指示您的监听器是否消耗此事件。重要的是,该事件可以有多个后续动作。因此,如果在接收到“按下”操作事件时返回false,则表示您未消耗该事件且也对该事件的任何其他操作(如手势或最终的“抬起”操作事件)不感兴趣。因此,您将不会被调用以处理该事件的任何其他动作。
实际上,取决于事件类型,您需要返回正确的值。

你能给我举个例子吗?我已经使用了MotionEvent,但是我只能调用clickEvent,不知道如何调用LongClick事件。你可以看一下我的代码并告诉我该怎么做。 - AndroidDev
1
当您在onTouch中消耗一个事件,且您不想调用onClick或onLongClick时,请返回true。当在onTouch中没有消耗任何事件,并且您想要调用onClick或onLongClick时,请返回false。 - xevincent

4

在OnTouch(View v,MotionEvent event)函数中,您需要返回false而不是true,以使控件上的其他监听器仍然处于活动状态。


2

看起来你遇到了引用问题。尝试像这样设置点击、长按和触摸监听器:

btnAdd.setOnClickListener(new Button.OnClickListener(){
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
    }
});

btnAdd.setOnLongClickListener(new Button.OnLongClickListener(){
    @Override
    public boolean onLongClick(View v) {
        // TODO Auto-generated method stub
        return false;
    }
});

btnAdd.setOnTouchListener(new Button.OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        return false;
    }
});

请确保您的类没有实现触摸监听器。您可以展示整个类的代码。 - Vineet Shukla
我认为你已经尝试过了...据我所知,我们必须使用Motion Event来捕获每个事件...它适用于Click事件...但如何使其适用于Longclick...我不知道... - AndroidDev

1
当您需要在同一视图上同时使用点击和触摸事件时,请使用GestureDetector。它还可以检测长按操作。

0

我不确定这是否是您想要实现的,因为您为按钮设置了onTouchListener - 但是如果您想要实现可滑动的活动(例如滑动屏幕并更改屏幕内容),您可以尝试让您的活动扩展下面发布的类,然后使用任何操作实现next()previous()方法。

import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.SimpleOnGestureListener;

public abstract class SwipeActivity extends Activity {
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
    private GestureDetector gestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        gestureDetector = new GestureDetector( new SwipeDetector() );
    }

    private class SwipeDetector extends SimpleOnGestureListener {       
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {

            // Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH, then dismiss the swipe.
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
                return false;

            // Swipe from right to left.
            // The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                next();
                return true;
            }

            // Swipe from left to right.
            // The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
            if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                previous();
                return true;
            }

            return false;
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //TouchEvent dispatcher.
        if (gestureDetector != null) {
            if (gestureDetector.onTouchEvent(ev))
                //If the gestureDetector handles the event, a swipe has been executed and no more needs to be done.
                return true;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    protected abstract void previous();
    protected abstract void next();
}

0
这是我如何解决ontouch和onlongclick同步的方法:
希望大家在查看这段代码后都能理解。当发生长按事件时,触摸监听器被设置为无监听器,当再次触摸视图时,无监听器会将视图的触摸监听器设置为其先前的监听器。
LinearLayout.LayoutParams longpressLP = new LinearLayout.LayoutParams(100,100);
    LinearLayout longpress = new LinearLayout(this);
    longpress.setBackgroundColor(Color.GREEN);
    //any layout you want to add your view in
    mainlayout.addView(longpress,longpressLP);



    final View.OnTouchListener buttontouch=new View.OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
                    if(event.getAction()==MotionEvent.ACTION_DOWN)
                Toast.makeText(getApplicationContext(), "Touched Down", Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(getApplicationContext(), "Touched", Toast.LENGTH_SHORT).show();
            return false;//IMPORTANT
        }
    };
    final View.OnTouchListener buttontouchnone=new View.OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {

            if(event.getAction()==MotionEvent.ACTION_DOWN)//IMPORTANT
            {
                v.setOnTouchListener(buttontouch);//IMPORTANT
                v.dispatchTouchEvent(event);//IMPORTANT
                Toast.makeText(getApplicationContext(), "ChangedListener", Toast.LENGTH_SHORT).show();
            }
            return false;//IMPORTANT
        }
    };
            //set listeners
    longpress.setOnTouchListener(buttontouch);
    longpress.setOnLongClickListener(new View.OnLongClickListener() {

        public boolean onLongClick(View v) {
            // TODO Auto-generated method stub
            Toast.makeText(getApplicationContext(), "LongClick", Toast.LENGTH_SHORT).show();
            v.setOnTouchListener(buttontouchnone);//IMPORTANT
            return true;//IMPORTANT
        }
    });

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