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

Перетаскивание повернутого вида путем настройки параметров макета

Я пытаюсь сделать вид, следуя моему пальцу, и сделаю поворот и масштабирование в мультитач со следующим кодом

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {

    final int action = motionEvent.getActionMasked();
    int newPosX,newPosY;
    switch (action) {
        case MotionEvent.ACTION_DOWN: {
            final int pointerIndex = motionEvent.getActionIndex();
            final float x = motionEvent.getX( pointerIndex);
            final float y = motionEvent.getY( pointerIndex);

            RelativeLayout.LayoutParams parms = (RelativeLayout.LayoutParams) view.getLayoutParams();

            // Remember where we started (for dragging)
            mLastTouchX = (int) x;
            mLastTouchY = (int) y;
            // Save the ID of this pointer (for dragging)
            mActivePointerId = motionEvent.getPointerId( 0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            if(motionEvent.getPointerCount()==2){
                float newDist = spacing(motionEvent);
                float scale = newDist / oldDist * view.getScaleX();
                view.setScaleY(scale);
                view.setScaleX(scale);

                float newAngle = rotation(motionEvent);
                float a = newAngle - oldAngle;
                view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start();
            }
            // Find the index of the active pointer and fetch its position
            final int pointerIndex =
                    motionEvent.findPointerIndex( mActivePointerId);

            final float x = motionEvent.getX( pointerIndex);
            final float y = motionEvent.getY( pointerIndex);

            // Calculate the distance moved
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

            layoutParams.leftMargin += dx;
            layoutParams.topMargin += dy;

            view.setLayoutParams(layoutParams);

            break;
        }
        case MotionEvent.ACTION_POINTER_DOWN:{
            oldDist = spacing(motionEvent);
            oldAngle = rotation(motionEvent);
            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 = motionEvent.getActionIndex();
            final int pointerId = motionEvent.getPointerId( pointerIndex);

            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = (int) motionEvent.getX( newPointerIndex);
                mLastTouchY = (int) motionEvent.getY( newPointerIndex);
                mActivePointerId = motionEvent.getPointerId( newPointerIndex);
            }
            break;
        }
    }
    return true;

}
    private float spacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return (float) Math.sqrt(x * x + y * y);
}

private float rotation(MotionEvent event) {
    double delta_x = (event.getX(0) - event.getX(1));
    double delta_y = (event.getY(0) - event.getY(1));
    double radians = Math.atan2(delta_y, delta_x);
    return (float) Math.toDegrees(radians);
}

Все работает хорошо , пока изображение не повернется. Когда он поворачивается выше 90 градусов, и мы пытаемся перетащить его, он прыгает вокруг точки касания. Я думаю, что это имеет какое-то отношение к

layoutParams.leftMargin += dx;
layoutParams.topMargin += dy;

setLayoutParams(layoutParams);

Я работаю над этой работой в течение последних двух дней без успеха.

ПРИМЕЧАНИЕ. То, что я пытаюсь достичь, - это сделать поворот вида и масштабировать с помощью двух пальцев (перетащите также одним пальцем) Я следил за кодом перетаскивания из документации Google, чтобы он не прыгал при переключении пальцев. Я использую это для поворота   view.animate(). rotationBy (a).setDuration(0).setInterpolator(новый LinearInterpolator()). start();

потому что, когда я использую view.setRotate(), вид вибрирует.

РЕДАКТИРОВАТЬ 1: Я удалил

layoutParams.leftMargin += dx;
layoutParams.topMargin += dy;

и заменил его на:

//To get the moved distance of the finger(X and Y)

float diffX = motionEvent.getX(pointerIndex) - mLastTouchX;
                    float diffY = motionEvent.getY(pointerIndex) - mLastTouchY;

//to get the distance from touch point and the top or left of the view
                    final float dx = motionEvent.getRawX() - (motionEvent.getRawX()-motionEvent.getX());
                    final float dy = motionEvent.getRawY() - (motionEvent.getRawY()-motionEvent.getY());
                    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

//Settings appropriate value for the margin top and margin left.

                    layoutParams.leftMargin = (int) ((( motionEvent.getRawX() )-dx )+ diffX );
                    layoutParams.topMargin = (int) ((( motionEvent.getRawY() )-dy )+ diffY );

Теперь даже после поворота вид не перемещается. но когда я переключаю активный палец, он прыгает от фактического положения.

В ACTION_POINTER_UP я делаю это, чтобы изменить сдвиг активного пальца

case MotionEvent.ACTION_POINTER_UP: {

                final int pointerIndex = motionEvent.getActionIndex();
                final int pointerId = motionEvent.getPointerId( pointerIndex);

                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    Log.d(TAG,"New pointer index :"+newPointerIndex);
                    mLastTouchX = (int) motionEvent.getX( newPointerIndex);
                    mLastTouchY = (int) motionEvent.getY( newPointerIndex);
                    mActivePointerId = motionEvent.getPointerId( newPointerIndex);
                }
                break;
            }
4b9b3361

Ответ 1

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

Вместо этого, если вы не хотите вникать в OpenGl, тогда мой совет будет Custom View, создайте класс extend View, который вы позже добавите в свой макет XML, <com.packagename.MyCustomView ... />. этот вид будет иметь размер всего экрана. Вы @Override метод onDraw(Canvas canvas), это даст вам холст представления, вы можете использовать Canvas для рисования графики в представлении.

напишите invalidate(); в конце вашего onDraw(), чтобы показать View, чтобы попытаться снова вызвать onDraw(), когда он доступен, вы должны прекратить его называть, как только пользователь перестанет касаться вашего вида, поэтому добавьте в него несколько логических значений.

теперь касания, вы можете зарегистрироваться, чтобы коснуться событий, как вы, но внутри своего пользовательского представления и использовать x, y и размер вашего представления из canvas.getWidth() и canvas.getHeight(), чтобы определить, что делать.

если вам нужен размер представления до того, как вы достигнете onDraw() переопределите onMeasure().

Summery

Это может показаться не таким легким, но оно быстрым и быстрым, графика будет гладкой, если вы хотите получить лучший результат и не боитесь большого количества кода, тогда вы можете посмотреть рисунок с использованием OpenGl, но Я бы не советовал вам, что вы пытаетесь сделать.

Надеюсь, я понял проблему и помог вам - Удачи!