【问题标题】:Get Touch Coordinates Relative To A View (ScreenToClient Equivalent?)获取相对于视图的触摸坐标(ScreenToClient 等效?)
【发布时间】:2011-12-09 21:16:43
【问题描述】:

我在我的 android 应用程序中向用户显示了一张图片。

我希望能够分辨出他们“触摸”图像的位置。

我可以通过实现 OnTouchListener 轻松获取屏幕坐标

 private OnTouchListener image_Listener = new OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_UP) {
            float x = event.getX();
            float y = event.getY();
            return true;
        }
        return false;
    }
};

但是,这些是绝对坐标。我真正需要的是将其转换为相对于视图的坐标的函数..

我已经进行了一些挖掘,但除了我自己尝试实现 ScreenToClient 方法之外,我似乎无法找到任何东西..

有没有人知道一个好的解决方案,还是我只能自己动手?

这似乎是一种可行的方法——这就是我要问的原因。

感谢大家的宝贵时间。

编辑:我不太确定坐标是否已经相对于视图。我本可以发誓阅读坐标是绝对的,但经过一些修补后 - 我的工作按预期工作.. 对不起那些吵闹的人。

【问题讨论】:

    标签: java android


    【解决方案1】:

    只是为了回答,触摸在某种程度上与视图相关。是的,它们是触摸的原始屏幕坐标。但是,由于您将触摸事件注册到视图本身,它只会在用户实际触摸视图时触发。这意味着,即使屏幕坐标是原始屏幕坐标,它们也在视图本身的范围内。

    如果你想得到被触摸视图的 x/y 坐标,那么你可以用屏幕坐标减去左坐标和 y 坐标的顶部坐标,如下所示:

    private OnTouchListener image_Listener = new OnTouchListener(){
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_UP) {
                float screenX = event.getX();
                float screenY = event.getY();
                float viewX = screenX - v.getLeft();
                float viewY = screenY - v.getTop();
                return true;
            }
            return false;
        }
    };
    

    这样,如果用户向下触摸了 40 x 像素,但左边距设置为 10,那么viewX 将是 30。如果您将视图向下移动 40 x 像素并且用户触摸了视图中的同一点,它仍然是 30。

    如果在 View 中包含 padding 作为 padding,即使它不显示任何内容,它仍然算作一个 View。

    编辑:

    我应该指出,皮埃尔所说的是真的。如果您触摸一个视图,那么即使您将手指拖到视图边界之外,它也会继续接收触摸事件,直到手指被抬起。这意味着,ACTION_UP 可以接收超出范围的视图的触摸坐标。

    【讨论】:

    • 我遇到了同样的问题。从教程中,这些方法,例如view.getLeft()。 “返回视图相对于其父级的位置。”通常,对于复杂的布局,被调查的视图不是屏幕视图的直接子级。所以Deev提到的方法不能总是适用。有什么新想法吗?
    • 嗯,我找到了一种方法:使用 View.getLocationOnScreen() 和/或 getLocationInWindow()。
    【解决方案2】:

    我刚遇到同样的问题,尝试 DeeV 解决方案时,getLeft() 和 getTop() 方法总是得到 0。由于无法更改布局(因为我认为 getTop/Left 仅与视图的父级相关),因此我必须弄清楚如何获取视图的绝对位置。

    这是使用 getLocationOnScreen(location) 的类似方法:

    protected Point getRelativePosition(View v, MotionEvent event) {
        int[] location = new int[2];
        v.getLocationOnScreen(location);
        float screenX = event.getRawX();
        float screenY = event.getRawY();
        float viewX = screenX - location[0];
        float viewY = screenY - location[1];
        return new Point((int) viewX, (int) viewY);
    }
    

    【讨论】:

    • 这个有效,而screenY - v.getTop() 无效(至少对我而言)
    • v.getTop() 也不适合我。有人知道为什么吗?
    • @eliasbagley:v.getTop() 相对于 v 的父级,而 screenY 相对于屏幕。仅当父级进入屏幕顶部时才有效。
    【解决方案3】:

    触摸事件坐标是相对于接收事件的视图。但是,它们不限于视图的大小,因为用户显然可以以相同的动作滑出视图。

    在触发 ACTION_UP 或 ACTION_CANCEL 之前,即使指针在视图之外,视图也会继续接收运动事件。

    你确定监听器在正确的视图中注册了吗?

    【讨论】:

    • 是的,我注册到了正确的视图。我的工作如我所愿。我只是让事情变得比他们需要的更困难。感谢您的回复。
    • 我认为“触摸事件坐标相对于视图...”是不正确的。例如,我在屏幕下方大约 2/3 处有一个按钮 - 连接到它,单击它的中心会得到一个比按钮高度大得多的 y 坐标。 QED。 OTOH,我是通过 Xamarin Forms 执行此操作的,因此附件完全有可能实际上不是按钮 [这将是 Xamarin 错误]。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多