Как получить правильные координаты (event.getX() / event.getY()) объекта с помощью OnTouchListener

У меня есть это:
исходный случай

и что я хочу именно то, чтобы показать часть растрового изображения через координаты(X,Y) объекта с OnTouchListener(оранжевый квадрат с точкой в ​​центре).

Так что проблема в том, что я хочу нарисовать часть изображения, как это показано на изображении (красная площадь "Область, которую я хочу" показать).
Таким образом, в этом случае, исключенный результат (часть растрового изображения):
ожидаемый результат
В настоящий момент я делаю так:

public boolean onTouch(View view, MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:

            Bitmap mBitmap = Bitmap.createBitmap(sourceBitmap,view.getX() - view.getWidth(),view.getY()-view.getHeight(),250,250);
            //other stuff to fill this portion of bitmap
            break;
    }

    return true;
}
}

И это не правильно.

Как я могу достичь этого? Перепробовал много формул, но не повезло. Какие-либо предложения?

PS Как я понимаю, event.getX ()/event.getY () получает относительные координаты (и мне не ясно, какие именно координаты получают от объекта просмотра изображений с помощью сенсорного слушателя (оранжевый квадрат с точкой в ​​центре), я имею в виду его получить центр этого объекта или Top.Left углы (X,Y))?

3 ответа

Решение

Чтобы было легко решить эту проблему.
Решение:
У меня есть объект (оранжевый квадрат) с OnTouchListener(например, он четырехугольник с размером 50dp Высота/ 50dp Ширина).
Поэтому view.getX()/view.getY() принимает относительные координаты (центр) объекта (который имеет OnTouchListener).
Итак, что мне было нужно:

//imageview parameters ,where i will show this part of bitmap
int Width = img.getWidth();
int Height = img.getHeight();
//after this,i make margin of my coords,via this simple formula -> Current Coord X - Width / 2 (same for Y)
 Bitmap mBitmap = Bitmap.createBitmap(sourceBitmap,view.getX() - Width / 2,view.getY()-Height / 2,Width,Height);  

И это все.
Наслаждайтесь!

Извините, глядя на решение более подробно, я думаю, что нашел его, и я на работе, так что вы можете попробовать это:

использование event.getX() не view.getX(), view.getX() возвращает позицию вида, которого вы касаетесь, а не интересующего вас события касания.

Это координата Y, которая, вероятно, будет инвертирована.

так event.getX() позиция сенсорного события.

event.getY() инвертированная позиция Y так getHeight() - event.getY() даст вам позицию Y вы после.

РЕДАКТИРОВАТЬ

В случае MOTION_MOVE getX и getY возвращают самые последние и сохраняют исторические данные. я думаю, что самый последний из них самый ценный, потому что именно там вы будете рисовать.

В этом случае используйте пакетную квоту из документации:

Пакетная обработка - http://developer.android.com/reference/android/view/MotionEvent.html

Для эффективности события движения с ACTION_MOVE могут объединять несколько выборок движения в пределах одного объекта. Самые последние координаты указателя доступны с использованием getX(int) и getY(int). Более ранние координаты в пакете доступны с использованием getHistoricalX(int, int) и getHistoricalY(int, int). Координаты являются "историческими" только в том случае, если они старше, чем текущие координаты в пакете; однако они по-прежнему отличаются от любых других координат, о которых сообщалось в предыдущих событиях движения. Чтобы обработать все координаты в пакете во временном порядке, сначала используйте исторические координаты, а затем - текущие координаты.

Вы должны получить координаты, как это, это даст вам координаты со ссылкой для просмотра, а не на экране.

                float xCord = event.getRawX()-v.getX();
                float yCord = event.getRawY()-v.getY();

К сожалению, нет простого способа решить эту проблему, если вы хотите по-настоящему обратиться к событию в рамках представления. Это все еще происходит на Android Pie на некоторых аппаратных средствах. Единственный способ справиться с нечетными событиями касания - это сравнить последние 3 события, если во время ACTION_MOVE не было странных движений, перед тем, как пересмотреть позицию представления. Ниже приведен пример проверки события на круговом изображении. Предполагается, что вы создали новую временную переменную double[3]:

  /**
     * This detects if your finger movement is a result of an actual raw touch event of if it's from a view jitter.
     * This uses 3 events of rotation as temporary storage so that differentiation between swapping touch events can be determined.
     *
     * @param newRotationValue
     */
    private boolean isRotationTouchEventConsistent(final double newRotationValue) {
        double evalValue = newRotationValue;

        if (Double.compare(newRotationStore[2], newRotationStore[1]) != 0) {
            newRotationStore[2] = newRotationStore[1];
        }
        if (Double.compare(newRotationStore[1], newRotationStore[0]) != 0) {
            newRotationStore[1] = newRotationStore[0];
        }

        newRotationStore[0] = evalValue;

        if (Double.compare(newRotationStore[2], newRotationStore[0]) == 0
                || Double.compare(newRotationStore[1], newRotationStore[0]) == 0
                || Double.compare(newRotationStore[2], newRotationStore[1]) == 0

                //Is the middle event the odd one out
                || (newRotationStore[0] > newRotationStore[1] && newRotationStore[1] < newRotationStore[2])
                || (newRotationStore[0] < newRotationStore[1] && newRotationStore[1] > newRotationStore[2])
        ) {
            return false;
        }
        return true;
    }
Другие вопросы по тегам