Подтвердить что ты не робот

Картинка/трансформирование холста Android не изменяет зону с кликом

У меня есть очень похожая проблема описанная здесь, за исключением использования ScaleAnimation, я разрешаю масштабирование масштабирования/панорамирования в моем RelativeLayout.

Масштабирование/панорамирование работает отлично, но независимо от того, как меняет просмотр/масштабирование моего вида, зона с кликами не изменяется вместе с визуальным представлением. Вот как выглядит мой диспетчерTouchEvent:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mScaleGestureDetector != null && mGestureDetector != null) {
        mScaleGestureDetector.onTouchEvent(ev);
        mGestureDetector.onTouchEvent(ev);
    }

    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();

            mLastTouchX = x;
            mLastTouchY = y;
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float y = ev.getY(pointerIndex);

            // Only move if the ScaleGestureDetector isn't processing a gesture.
            if (!mScaleGestureDetector.isInProgress() && mScaleFactor > 1f) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                float newPosX = mPosX + dx;
                float newPosY = mPosY + dy;
                if (isCoordinateInBound(newPosX, mScreenSize.x))
                    mPosX = newPosX;
                if (isCoordinateInBound(newPosY, mScreenSize.y))
                    mPosY = newPosY;

                invalidate();
            }

            mLastTouchX = x;
            mLastTouchY = y;

            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
            }
            break;
        }
    }

    return super.dispatchTouchEvent(ev);
}

и мой dispatchDraw:

protected void dispatchDraw(Canvas canvas) {
    canvas.save(Canvas.MATRIX_SAVE_FLAG);
    canvas.translate(mPosX, mPosY);

    canvas.scale(mScaleFactor, mScaleFactor);
    super.dispatchDraw(canvas);
    canvas.restore();
}

Как вы изменяете область с кликами в соответствии с измененной шкалой/преобразованием холста?

4b9b3361

Ответ 1

Поскольку вы уже выполняете onverriding dispatchTouchEvent, вы можете попробовать следующее:

  • вручную оценивайте каждый MotionEvent, рассматривая текущее преобразование масштабирования/панорамирования; вы можете создать новый MotionEvent (пусть он называет его FakeMotionEvent), применив преобразование трансфокатора в обратном направлении/панорамирование к исходному MotionEvent m.
  • Убедитесь, что FakeMotionEvent перехватывает конкретный View v; это означает, что пользователь прикасается к позиции, которая представляет положение пользователя в видимой области v.
  • Если FakeMotionEvent перехватывает v, потребляет текущий MotionEvent и вызывает v.dispatchTouchEvent(m);

СОВЕТ. Вы можете использовать метод ниже, чтобы оценить, если a MotionEvent перехватывает View с определенной степенью допуска:

private boolean intercept(MotionEvent ev, View view, float boundingBoxTolerance){
    if (boundingBoxTolerance < 1.0f) {
        boundingBoxTolerance = 1.0f;
    }
    try {
        if (ev != null && view != null) {
            int coords[] = new int[2];
            view.getLocationOnScreen(coords);
            if (ev.getRawX() >= ((float)coords[0]) / boundingBoxTolerance && ev.getRawX() <= coords[0] + ((float) view.getWidth()) * boundingBoxTolerance) {
                if(ev.getRawY() >= ((float)coords[1]) / boundingBoxTolerance && ev.getRawY() <= coords[1] + ((float) view.getHeight()) * boundingBoxTolerance)
                    return true;
            }
        }
    }
    catch (Exception e) {}
    return false;
}

Ответ 2

Я предполагаю, что вы используете Просмотр анимаций, я предпочту использовать Имена свойств вместо

выдержка из документации по Android (см. выделенную)

Система анимации просмотра обеспечивает возможность просмотра только анимации объекты, поэтому, если вы хотите анимировать объекты без просмотра, вам нужно для этого выполните свой собственный код. Система анимации представления также ограниченный тем, что он раскрывает лишь несколько аспектов объект для анимации, такой как масштабирование и вращение представления, но не например, цвет фона.

Другим недостатком системы анимации просмотра является то, что она только изменен, когда был отображен вид, а не фактический вид. Для Например, если вы анимировали кнопку для перемещения по экрану, кнопка рисует правильно, но фактическое местоположение, в которое вы можете щелкнуть кнопка не изменяется, поэтому вам нужно реализовать свою собственную логику для отрегулируйте это.

С системой анимации свойств эти ограничения полностью удалены, и вы можете анимировать любое свойство любого объекта (виды и non-Views), и сам объект фактически модифицируется. Недвижимость система анимации также более надежна в том, как она выполняется анимация. На высоком уровне вы назначаете аниматоры свойствам что вы хотите оживить, например, цвет, положение или размер и можете определить аспекты анимации, такие как интерполяция и синхронизация нескольких аниматоров.

Однако система анимации просмотра занимает меньше времени для настройки и требует меньше кода для записи. Если анимация просмотра выполняет все что вам нужно сделать, или если ваш существующий код уже работает так вы хотите, нет необходимости использовать систему анимации свойств. Это также может иметь смысл использовать обе системы анимации для разных ситуаций, если возникает прецедент.