Получить Координаты Касания Относительно Вида (Эквивалент ScreenToClient?)


У меня есть изображение, которое я показываю пользователю в моем приложении для 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..

Кто-нибудь знает хорошее решение для этого, или мне просто придется свернуть свой собственный?

Похоже, что такой метод был бы доступен - вот почему я спрашиваю.

Спасибо всем за ваше время.

EDIT: я не уверен, что координаты уже не относятся к виду. Я мог бы поклясться, читая, что координаты были абсолютными, но после некоторых манипуляций-у меня все работает, как я и ожидал.. Извините за шум парни.

3 15

3 ответа:

Просто чтобы ответить, прикосновения в некотором смысле относительны к виду. Да, это необработанные координаты экрана касания. Однако, поскольку вы регистрируете событие касания в самом представлении, оно будет срабатывать только в том случае, если пользователь действительно коснется представления. Это означает, что даже если координаты экрана являются необработанными координатами экрана, они находятся в пределах самого представления.

Если вы хотите получить координаты 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.

Это становится немного сложнее, если вы включили заполнение, поскольку заполнение в представлении все еще считается представлением, даже если оно не отображается что-нибудь.

Правка:

Я должен отметить, что то, что сказал Пьер, - правда. Если вы коснетесь вида, то он будет продолжать получать события касания до тех пор, пока палец не будет поднят, даже если вы переместите палец за пределы вида. Это означает, что ACTION_UP может получать координаты касания для вашего представления, которые не находятся в пределах границ.

У меня только что была та же проблема, и, пытаясь решить DeeV, я всегда получал 0 как из методов getLeft (), так и из методов getTop (). Поскольку изменение макета не было вариантом (потому что я думаю, что 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);
}

Координаты события касания относятся к виду, который получает событие. Однако они не ограничиваются размером представления, поскольку пользователь, очевидно, может скользить вне представления в том же движении.

До тех пор, пока не будет вызвано действие ACTION_UP или ACTION_CANCEL, представление будет продолжать получать события движения, даже если указатель находится вне представления.

Вы уверены, что слушатель зарегистрирован в правильном представлении?