可以用一根或两根手指旋转和缩放的自定义图像视图

时间:2018-08-06 09:14:27

标签: android

我正在尝试开发一个自定义视图,该视图可以使用位于右下角的按钮(也可以用两根手指)旋转。

使用该链接https://github.com/ryanch741/android-view-rotate-zoom-single-finger

我正在尝试修改其自定义视图。为此,我使用了在该项目https://github.com/thuytrinh/android-collage-views

中创建的MultiTouchListener类

,因此我可以使用按钮和两个手指。

但是当我使用两根手指时,我无法将按钮保持在右下角。我试图使用视图矩阵没有成功

那么在旋转,缩放和平移动作之后,如何计算imageView的新位置?

这是我的课程

class ViewOnTouchListener2 implements View.OnTouchListener {

private final static String LOG_TAG = ViewOnTouchListener2.class.getSimpleName();

Point pushPoint;
int lastImgLeft;
int lastImgTop;
FrameLayout.LayoutParams viewLP;
FrameLayout.LayoutParams pushBtnLP;
int lastPushBtnLeft;
int lastPushBtnTop;
private View mPushView;

RectF mRect;


/**/

private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;

public boolean isRotateEnabled = true;
public boolean isTranslateEnabled = true;
public boolean isScaleEnabled = true;
public float minimumScale = 0.5f;
public float maximumScale = 10.0f;

private ScaleGestureDetector mScaleGestureDetector;

/**/


ViewOnTouchListener2(View mPushView) {
    this.mPushView = mPushView;
    mScaleGestureDetector = new ScaleGestureDetector(new ViewOnTouchListener2.ScaleGestureListener());

}

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

    int pointerCount = event.getPointerCount();

    mScaleGestureDetector.onTouchEvent(view, event);

    int action = event.getAction();

    switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN:

            if (null == viewLP) {
                viewLP = (FrameLayout.LayoutParams) view.getLayoutParams();
            }

            if (null == pushBtnLP) {
                pushBtnLP = (FrameLayout.LayoutParams) mPushView.getLayoutParams();
            }

            // Save the ID of this pointer.
            mActivePointerId = event.getPointerId(0);

            //pushPoint = getRawPoint(event);
            pushPoint = getRawPoint(event,mActivePointerId,viewLP);

            //Log.d(LOG_TAG," pushPoint x "+pushPoint.x);
            //Log.d(LOG_TAG," pushPoint y "+pushPoint.y);

            lastImgLeft = viewLP.leftMargin;

            lastImgTop = viewLP.topMargin;

            //mRect = new RectF (viewLP.leftMargin, viewLP.topMargin, viewLP.rightMargin, viewLP.bottomMargin);
            //mRect = new RectF (viewLP.leftMargin, viewLP.topMargin, viewLP.rightMargin, viewLP.bottomMargin);


            Log.d(LOG_TAG," lastImgLeft  "+lastImgLeft);
            Log.d(LOG_TAG," lastImgTop "+lastImgTop);


            lastPushBtnLeft = pushBtnLP.leftMargin;

            lastPushBtnTop = pushBtnLP.topMargin;



            break;
        case MotionEvent.ACTION_MOVE:

            //un seul doigt

            int pointerIndex = event.findPointerIndex(mActivePointerId);

            if (pointerIndex != -1) {


                //Point newPoint = getRawPoint(event);
                Point newPoint = getRawPoint(event,pointerIndex,viewLP);
                float moveX = newPoint.x - pushPoint.x;
                float moveY = newPoint.y - pushPoint.y;

                if (!mScaleGestureDetector.isInProgress()) {


                    viewLP.leftMargin = (int) (lastImgLeft + moveX);
                    viewLP.topMargin = (int) (lastImgTop + moveY);
                    view.setLayoutParams(viewLP);


                    pushBtnLP.leftMargin = (int) (lastPushBtnLeft + moveX);
                    pushBtnLP.topMargin = (int) (lastPushBtnTop + moveY);
                    mPushView.setLayoutParams(pushBtnLP);
                }

            }


            break;

        case MotionEvent.ACTION_CANCEL:
            mActivePointerId = INVALID_POINTER_ID;
            break;

        case MotionEvent.ACTION_UP:
            mActivePointerId = INVALID_POINTER_ID;
            break;

        case MotionEvent.ACTION_POINTER_UP: {
            // Extract the index of the pointer that left the touch sensor.
            int pointerIndex2 = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;

            int pointerId = event.getPointerId(pointerIndex2);

            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new

                // active pointer and adjust accordingly.
                int newPointerIndex = pointerIndex2 == 0 ? 1 : 0;

                //mPrevX = event.getX(newPointerIndex);
                //mPrevY = event.getY(newPointerIndex);
                pushPoint = getRawPoint(event,newPointerIndex,viewLP);

                lastImgLeft = viewLP.leftMargin;

                lastImgTop = viewLP.topMargin;

                lastPushBtnLeft = pushBtnLP.leftMargin;

                lastPushBtnTop = pushBtnLP.topMargin;

                mActivePointerId = event.getPointerId(newPointerIndex);
            }
        }
            break;

    }
    return false;
}


private Point getRawPoint(MotionEvent event) {

    //Log.d(LOG_TAG,"event.getRawX() : "+event.getRawX());
    //Log.d(LOG_TAG,"event.getRawY() : "+event.getRawY());

    return new Point((int) event.getRawX(), (int) event.getRawY());
}

private Point getRawPoint(MotionEvent event,int pointerIndex,FrameLayout.LayoutParams viewLp) {


    //Log.d(LOG_TAG,"event.getRawX() ajusté : "+(viewLp.leftMargin + (int) event.getX(pointerIndex)));
    //Log.d(LOG_TAG,"event.getRawY() ajusté : "+(viewLp.topMargin+ (int) event.getY(pointerIndex)));

    return new Point(viewLp.leftMargin + (int) event.getX(pointerIndex),
            viewLp.topMargin+ (int) event.getY(pointerIndex));
}


private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    private float mPivotX;
    private float mPivotY;
    private Vector2D mPrevSpanVector = new Vector2D();

    @Override
    public boolean onScaleBegin(View view, ScaleGestureDetector detector) {
        mPivotX = detector.getFocusX();
        mPivotY = detector.getFocusY();
        mPrevSpanVector.set(detector.getCurrentSpanVector());

        return true;
    }

    @Override
    public boolean onScale(View view, ScaleGestureDetector detector) {
        ViewOnTouchListener2.TransformInfo info = new ViewOnTouchListener2.TransformInfo();
        info.deltaScale = isScaleEnabled ? detector.getScaleFactor() : 1.0f;
        info.deltaAngle = isRotateEnabled ? Vector2D.getAngle(mPrevSpanVector, detector.getCurrentSpanVector()) : 0.0f;
        info.deltaX = isTranslateEnabled ? detector.getFocusX() - mPivotX : 0.0f;
        info.deltaY = isTranslateEnabled ? detector.getFocusY() - mPivotY : 0.0f;
        info.pivotX = mPivotX;
        info.pivotY = mPivotY;
        info.minimumScale = minimumScale;
        info.maximumScale = maximumScale;

        move(view, info);

        return false;
    }
}

private  void move(View view, ViewOnTouchListener2.TransformInfo info) {

    computeRenderOffset(view, info.pivotX, info.pivotY);

    adjustTranslation(view, info.deltaX, info.deltaY);


    // Assume that scaling still maintains aspect ratio.
    float scale = view.getScaleX() * info.deltaScale;
    scale = Math.max(info.minimumScale, Math.min(info.maximumScale, scale));
    view.setScaleX(scale);
    view.setScaleY(scale);

    //Log.d(LOG_TAG,"scale : "+scale);
    float rotation = adjustAngle(view.getRotation() + info.deltaAngle);
    view.setRotation(rotation);


}

private void setPushButton(View view,TransformInfo info,float rotation){


    float[] prevPoint = {0.0f, 0.0f};
    view.getMatrix().mapPoints(prevPoint);

    view.setPivotX(info.pivotX);
    view.setPivotY(info.pivotY);

    float[] currPoint = {0.0f, 0.0f};
    view.getMatrix().mapPoints(currPoint);

    float offsetX = currPoint[0] - prevPoint[0];
    float offsetY = currPoint[1] - prevPoint[1];

    //view.setTranslationX(view.getTranslationX() - offsetX);
    //view.setTranslationY(view.getTranslationY() - offsetY);

    //Point newPushButtonPosition = getPositionOfPushButton(view,(FrameLayout.LayoutParams) view.getLayoutParams());

    //Log.d(LOG_TAG," new x "+currPoint[0]);
    //Log.d(LOG_TAG," new y "+currPoint[1]);

    pushBtnLP.leftMargin = (int)(view.getTranslationX());
    pushBtnLP.topMargin = (int)(view.getTranslationY());
    mPushView.setLayoutParams(pushBtnLP);
}

private  Point getPositionOfPushButton(View view,FrameLayout.LayoutParams layoutParams){

    //Log.d(LOG_TAG," layoutParams.leftMargin x "+layoutParams.leftMargin);
    //Log.d(LOG_TAG," layoutParams.topMargin y "+layoutParams.topMargin);
    //Log.d(LOG_TAG," width : "+view.getWidth()*view.getScaleX());
    //Log.d(LOG_TAG," getHeight : "+view.getHeight()*view.getScaleY());



    return new Point(layoutParams.leftMargin+ view.getWidth()*view.getScaleX(),
            layoutParams.topMargin+view.getHeight()*view.getScaleY());

}

private static void adjustTranslation(View view, float deltaX, float deltaY) {
    float[] deltaVector = {deltaX, deltaY};
    view.getMatrix().mapVectors(deltaVector);
    view.setTranslationX(view.getTranslationX() + deltaVector[0]);
    view.setTranslationY(view.getTranslationY() + deltaVector[1]);
}

private static void computeRenderOffset(View view, float pivotX, float pivotY) {
    if (view.getPivotX() == pivotX && view.getPivotY() == pivotY) {
        return;
    }

    float[] prevPoint = {0.0f, 0.0f};
    view.getMatrix().mapPoints(prevPoint);

    view.setPivotX(pivotX);
    view.setPivotY(pivotY);

    float[] currPoint = {0.0f, 0.0f};
    view.getMatrix().mapPoints(currPoint);

    float offsetX = currPoint[0] - prevPoint[0];
    float offsetY = currPoint[1] - prevPoint[1];

    view.setTranslationX(view.getTranslationX() - offsetX);
    view.setTranslationY(view.getTranslationY() - offsetY);
}

private static float adjustAngle(float degrees) {
    if (degrees > 180.0f) {
        degrees -= 360.0f;
    } else if (degrees < -180.0f) {
        degrees += 360.0f;
    }

    return degrees;
}

private class TransformInfo {

    public float deltaX;
    public float deltaY;
    public float deltaScale;
    public float deltaAngle;
    public float pivotX;
    public float pivotY;
    public float minimumScale;
    public float maximumScale;
}

}

0 个答案:

没有答案