OnClickListener-事件的x,y位置?


85

我有一个从View派生的自定义视图。我想在单击视图时以及单击发生位置的x,y位置时收到通知。与长按相同。

看起来要这样做,我需要重写onTouchEvent()。但是,没有办法从事件获取事件的x,y位置OnClickListener吗?

如果不是,那么判断运动事件是“真实”点击还是长按等的好方法是什么?将onTouchEvent产生快速连续等许多事件

Answers:


91

谢谢。那正是我想要的。我的代码现在是:

imageView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN){
                textView.setText("Touch coordinates : " +
                        String.valueOf(event.getX()) + "x" + String.valueOf(event.getY()));
            }
            return true;
        }
    });

正是Mark所要求的...


4
这些坐标是否在视图本地?
奈杰尔2014年

7
onTouch处理程序是否应该返回,false这样它才不会阻止触摸事件?(如果侦听器已使用该事件,则View.OnTouchListener.onTouch返回true,否则返回false。)
ehartwell 2014年

5
好吧,这不是“精确”的,因为OnClickListener放开手指时会触发,因此ACTION_UP有一定的局限性:如果执行了挥动(滑动)手势,则OnClickListener不会触发,但ACTION_UP仍会被处理。
Alex Semeniuk 2014年

我正在尝试在单击的坐标上写文本。我尝试在坐标处编写文本,(event.getX(), event.getY()) 但是书写位置不正确。
王子


26

完整的例子

其他答案缺少一些细节。这是一个完整的例子。

public class MainActivity extends AppCompatActivity {

    // class member variable to save the X,Y coordinates
    private float[] lastTouchDownXY = new float[2];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // add both a touch listener and a click listener
        View myView = findViewById(R.id.my_view);
        myView.setOnTouchListener(touchListener);
        myView.setOnClickListener(clickListener);
    }

    // the purpose of the touch listener is just to store the touch X,Y coordinates
    View.OnTouchListener touchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            // save the X,Y coordinates
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                lastTouchDownXY[0] = event.getX();
                lastTouchDownXY[1] = event.getY();
            }

            // let the touch event pass on to whoever needs it
            return false;
        }
    };

    View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // retrieve the stored coordinates
            float x = lastTouchDownXY[0];
            float y = lastTouchDownXY[1];

            // use the coordinates for whatever
            Log.i("TAG", "onLongClick: x = " + x + ", y = " + y);
        }
    };
}

概要

  • 添加一个类变量来存储坐标
  • 使用 OnTouchListener
  • OnClickListener

1
可以使用Point()代替2个空格的float Array。
ZooMagic

点具有整数类型的X和Y。坐标是浮点值。如果我使用Point类,我想我会失去精度...。我在Android中是个新手,可能是我错过了一些东西。
mboada

@mboada,你是对的。PointF会更好。
Suragch '19

应该有一种避免onTouchListener的方法,而仅使用onClickListener。某种程度上,ContextMenu不需要它。单击某个项目并以视图作为锚点显示菜单时,它会知道将其放置在触摸位置附近的位置。看到这里:stackoverflow.com/q/57290574/878126。你知道这怎么可能吗?如果是这样,请考虑在那里回答。
Android开发人员

3

覆盖onTouchEvent(MotionEvent ev)

然后,您可以执行以下操作:

ev.getXLocation()

或类似的东西。有一个屁股。


2
嗨,汤姆,是的,我们可以使用onTouchEvent,但是我们需要自己处理点击和长按之间的区别,不是吗?他们不会为您提供一种了解OnClickListener等中单击或长时间单击发生在何处的方式,这是没有道理的?谢谢
马克

21
您要做的就是记录上一个ACTION_UP或ACTION_MOVE事件的x和y位置,并在OnClickListener中使用这些值。
罗曼·盖伊2009年

@RomainGuy但是,您还必须计算两点之间的距离才能确定单击。如果您在(0,0)收到ACTION_DOWN事件,然后在(100,100)收到ACTION_UP事件,则绝对不是单击。
TheRealChx101

@ chx101,RomainGuy的意思是(我认为)是,如果您仅在touchevent上记录了最后一个action_up坐标,那么这些就是您可以在onclick中使用的坐标。但是我认为实际上需要将视图子类化,否则就不会调用onclick。您还可以像在stackoverflow.com/questions/19538747/…中那样,将轻击检测为手势检测器
Lassi Kinnunen 2016年

0

您可以在Kotlin中创建扩展功能,如下所示:

fun View.setOnClickListenerWithPoint(action: (Point) -> Unit) {
    val coordinates = Point()
    val screenPosition = IntArray(2)
    setOnTouchListener { v, event ->
        if (event.action == MotionEvent.ACTION_DOWN) {
            v.getLocationOnScreen(screenPosition)
            coordinates.set(event.x.toInt() + screenPosition[0], event.y.toInt() + screenPosition[1])
        }
        false
    }
    setOnClickListener {
        action.invoke(coordinates)
    }
}

如果需要长按-只需更换 setOnClickListener

我使用getLocationOnScreen()是因为我需要RecyclerView的ViewHolder的坐标

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.