Android 相对论上矩阵变换后的接触位置错误

Android 相对论上矩阵变换后的接触位置错误,android,zooming,android-relativelayout,pan,Android,Zooming,Android Relativelayout,Pan,我正在实现一个函数,在一个相对的窗口中执行缩放和平移,我几乎完成了。但是,当我在布局中有视图并且应用了转换时,这些视图的触感不会更新,然后就失去了对它们的跟踪 通过执行转换,我需要对视图进行触摸,以根据缩放和平移进行操作 我在下面分享我的代码并请求帮助,这样我就可以完成它 公共类ZoomLayout扩展了RelativeLayout实现OnTouchListener、OnDoubleTapListener和OnTestureListener { //=======================

我正在实现一个函数,在一个相对的窗口中执行缩放和平移,我几乎完成了。但是,当我在布局中有视图并且应用了转换时,这些视图的触感不会更新,然后就失去了对它们的跟踪

通过执行转换,我需要对视图进行触摸,以根据缩放和平移进行操作

我在下面分享我的代码并请求帮助,这样我就可以完成它

公共类ZoomLayout扩展了RelativeLayout实现OnTouchListener、OnDoubleTapListener和OnTestureListener {

//===================================================================================
//========================================================================前庭====================================
// ===================================================================================
专用浮点currentScaleFactor=1.0f;
私有浮点previousScaleFactor=1.0f;
私人scalegestruedetector scalegestruedetector;
私人手势检测器;
私人股本;
私人股本;
私人浮动汇率;
私人浮动货币;
私人舞台;
私人浮式舞台;
私人浮动利率;
私有浮动初始值;
专用浮点最大刻度=5f;
私人浮动最小刻度=0.3f;
私人舞台;
私人舞台;
私有布尔值firstTimeOnEvent=true;
私有布尔zoomEnable=true;
私有布尔值oneFingerMoveEnable=false;
私有布尔twoFingersMoveEnable=true;
私有布尔值doubleTapZoomEnable=true;
私有矩阵savedMatrix=null;
private boolean onScale=false;
私有浮动差分法;
私人浮动差异计量;
private List listeners=new CopyOnWriteArrayList();
// ===================================================================================
//==================================================================承包商==================================
// ===================================================================================
公共缩放布局(上下文)
{
超级(上下文);
setWillNotDraw(假);
savedMatrix=新矩阵();
savedMatrix.reset();
scalegestruedetector=新的scalegestruedetector(getContext(),new ZoomScale());
gestureDetector=新的gestureDetector(上下文,此);
gestureDetector.setOnDoubleTapListener(此);
this.setOnTouchListener(this);
}
公共缩放布局(上下文、整数宽度、整数高度)
{
这(上下文);
此.widthStage=宽度;
this.heightStage=高度;
}
// ===================================================================================
//===================================================方法=====================================
// ===================================================================================
公共空间设置ZoomScale(浮动比例)
{
currentScaleFactor=比例;
previousScaleFactor=比例;
savedMatrix.reset();
X实际值=0;
实际值=0;
xPrevious=0;
yPrevious=0;
float maxLeft=((浮点)(widthStage*0.5)-(浮点)(widthStage*currentScaleFactor*0.5));
float maxTop=((float)(heightStage*0.5)-(float)(heightStage*currentScaleFactor*0.5));
savedMatrix.postScale(currentScaleFactor,currentScaleFactor);
savedMatrix.postTranslate(maxLeft,maxTop);
使无效();
requestLayout();
leftStage=0;
顶层=0;
}
public void addZoomListener(ZoomListener侦听器)
{
添加(侦听器);
}
公共无效删除ZoomListener(ZoomListener侦听器)
{
删除(侦听器);
}
// ===================================================================================
//==========================================================活动=====================================
// ===================================================================================
@凌驾
公共布尔onTouch(视图v,运动事件)
{
如果(可缩放)
{
开关(event.getAction()&MotionEvent.ACTION\u掩码)
{
case MotionEvent.ACTION\u DOWN:
打破
case MotionEvent.ACTION\u指针\u向下:
firstTimeOnEvent=true;
打破
case MotionEvent.ACTION\u UP:
firstTimeOnEvent=true;
打破
case MotionEvent.ACTION\u指针\u向上:
打破
case MotionEvent.ACTION\u取消:
firstTimeOnEvent=true;
打破
case MotionEvent.ACTION\u移动:
打破
}
scalegestruedetector.onTouchEvent(事件);
手势检测器。onTouchEvent(事件);
}
其他的
{
返回false;
}
for(int i=0;i=752)
{
maxTop=-((浮动)(h
// ===================================================================================
// ==================================== ATRIBUTES ====================================
// ===================================================================================


private float currentScaleFactor = 1.0f;

private float previousScaleFactor = 1.0f;

private ScaleGestureDetector scaleGestureDetector;

private GestureDetector gestureDetector;

private float xPrevious;

private float yPrevious;

private float xActual;

private float yActual;

private float leftStage;

private float topStage;

private float xInitial;

private float yInitial;

private float maxScale = 5f;

private float minScale = 0.3f;

private int widthStage;

private int heightStage;

private boolean firstTimeOnEvent = true;

private boolean zoomEnable = true;

private boolean oneFingerMoveEnable = false;

private boolean twoFingersMoveEnable = true;

private boolean doubleTapZoomEnable = true;

private Matrix savedMatrix = null;

private boolean onScale = false;

private float diferenceFromScaleX;

private float diferenceFromScaleY;

private List<ZoomListener> listeners = new CopyOnWriteArrayList<ZoomListener>();

// ===================================================================================
// =================================== CONTRUCTORS ==================================
// ===================================================================================

public ZoomLayout(Context context)
{
    super(context);

    setWillNotDraw(false);

    savedMatrix = new Matrix();

    savedMatrix.reset();

    scaleGestureDetector = new ScaleGestureDetector(getContext(), new ZoomScale());

    gestureDetector = new GestureDetector(context, this);

    gestureDetector.setOnDoubleTapListener(this);


    this.setOnTouchListener(this);
}

public ZoomLayout(Context context, int width, int height)
{
    this(context);

    this.widthStage = width;
    this.heightStage = height;
}

// ===================================================================================
// ===================================== METHODS =====================================
// ===================================================================================

public void setZoomScale(float scale)
{
    currentScaleFactor = scale;
    previousScaleFactor = scale;

    savedMatrix.reset();

    xActual = 0;
    yActual = 0;
    xPrevious = 0;
    yPrevious = 0;

    float maxLeft = ((float) (widthStage * 0.5) - (float) (widthStage * currentScaleFactor * 0.5));
    float maxTop = ((float) (heightStage * 0.5) - (float) (heightStage * currentScaleFactor * 0.5));

    savedMatrix.postScale(currentScaleFactor, currentScaleFactor);
    savedMatrix.postTranslate(maxLeft, maxTop);

    invalidate();
    requestLayout();

    leftStage = 0;
    topStage = 0; 
}


public void addZoomListener(ZoomListener listener)
{
    listeners.add(listener);
}


public void removeZoomListener(ZoomListener listener)
{
    listeners.remove(listener);
}

// ===================================================================================
// ===================================== EVENTS =====================================
// ===================================================================================

@Override
public boolean onTouch(View v, MotionEvent event)
{
    if (zoomEnable)
    {
        switch (event.getAction() & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_POINTER_DOWN:

                firstTimeOnEvent = true;

                break;

            case MotionEvent.ACTION_UP:

                firstTimeOnEvent = true;

                break;

            case MotionEvent.ACTION_POINTER_UP:

                break;

            case MotionEvent.ACTION_CANCEL:

                firstTimeOnEvent = true;

                break;

            case MotionEvent.ACTION_MOVE:

                break;
        }

        scaleGestureDetector.onTouchEvent(event);

        gestureDetector.onTouchEvent(event);

    }
    else
    {
        return false;
    }

    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onTouch(v, event);
    }

    return true;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    onTouchEvent(ev);
    return super.onInterceptTouchEvent(ev);
}

@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {

    return super.invalidateChildInParent(location, dirty);
}


@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
    int count = getChildCount();
    for(int i=0;i<count;i++){
        View child = getChildAt(i);
        if(child.getVisibility()!=GONE){
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)child.getLayoutParams();
            child.layout(
                (int)(params.leftMargin*currentScaleFactor),
                (int)(params.topMargin*currentScaleFactor),
                (int)((params.leftMargin + child.getMeasuredWidth())*currentScaleFactor ),
                (int)((params.topMargin + child.getMeasuredHeight())*currentScaleFactor)
                );
            child.setLayoutParams(params);

        }
    }
}

@Override
protected void dispatchDraw(Canvas canvas)
{
    canvas.setMatrix(savedMatrix);

    super.dispatchDraw(canvas);
}


private class ZoomScale extends ScaleGestureDetector.SimpleOnScaleGestureListener
{

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector)
    {
        onScale = true;


        for (int i = 0; i < listeners.size(); i++)
        {
            listeners.get(i).onScaleBegin(detector);
        }

        return super.onScaleBegin(detector);
    }


    @Override
    public void onScaleEnd(ScaleGestureDetector detector)
    {

        onScale = false;


        diferenceFromScaleX = detector.getFocusX() - xActual;
        diferenceFromScaleY = detector.getFocusY() - yActual;


        for (int i = 0; i < listeners.size(); i++)
        {
            listeners.get(i).onScaleEnd(detector);
        }

        super.onScaleEnd(detector);
    }


    @Override
    public boolean onScale(ScaleGestureDetector detector)
    {

        xPrevious = xActual;
        yPrevious = yActual;


        xActual = scaleGestureDetector.getFocusX();
        yActual = scaleGestureDetector.getFocusY();

        if (!firstTimeOnEvent)
        {

            currentScaleFactor = (currentScaleFactor * detector.getScaleFactor());


            currentScaleFactor = (Math.max(Math.min(currentScaleFactor, maxScale), minScale));


            float diferencaScale = (currentScaleFactor / previousScaleFactor);


            float x = xActual - xPrevious;


            float y = yActual - yPrevious;


            savedMatrix.postScale(diferencaScale, diferencaScale, xInitial - x, yInitial - y);

            savedMatrix.postTranslate(x, y);

            float[] values = new float[9];

            savedMatrix.getValues(values);

            float leftAux = (float) values[Matrix.MTRANS_X];
            float topAux = (float) values[Matrix.MTRANS_Y];


            float maxLeft = 0;
            float maxTop = 0;

            if (widthStage * currentScaleFactor >= 1280)
            {

                maxLeft = -((float) (widthStage * currentScaleFactor) - (float) 1280);

                if (leftAux < 0)
                {

                    if (leftAux < maxLeft)
                    {

                        maxLeft -= leftAux;
                    }
                    else
                    {

                        maxLeft = 0;
                    }
                }
                else
                {

                    maxLeft = -leftAux;
                }
            }
            else
            {

                maxLeft = ((float) (widthStage * 0.5) - (float) (widthStage * currentScaleFactor * 0.5));

                maxLeft -= leftAux;
            }

            if (heightStage * currentScaleFactor >= 752)
            {

                maxTop = -((float) (heightStage * currentScaleFactor) - (float) 752);

                if (topAux < 0)
                {

                    if (topAux < maxTop)
                    {

                        maxTop -= topAux;
                    }
                    else
                    {

                        maxTop = 0;
                    }
                }
                else
                {

                    maxTop = -topAux;
                }
            }
            else
            {

                maxTop = ((float) (752 * 0.5) - (float) (heightStage * currentScaleFactor * 0.5));


                maxTop -= topAux;
            }


            savedMatrix.postTranslate(maxLeft, maxTop);


            previousScaleFactor = currentScaleFactor;

            invalidate();
            requestLayout();
        }
        else
        {
            firstTimeOnEvent = false;

            xInitial = detector.getFocusX();
            yInitial = detector.getFocusY();

            previousScaleFactor = currentScaleFactor;
        }

        float[] values = new float[9];
        savedMatrix.getValues(values);

        leftStage = values[Matrix.MTRANS_X];
        topStage = values[Matrix.MTRANS_Y];

        for (int i = 0; i < listeners.size(); i++)
        {
            listeners.get(i).onScale(detector);
        }

        atualizaParametrosView();

        return true;
    }
}

public boolean onDoubleTap(MotionEvent e)
{
    if (doubleTapZoomEnable)
    {
        currentScaleFactor = 1.0f;
        previousScaleFactor = 1.0f;

        savedMatrix.reset();

        xActual = 0;
        yActual = 0;
        xPrevious = 0;
        yPrevious = 0;
        savedMatrix.postTranslate(0, 0);

        invalidate();
        requestLayout();

        leftStage = 0;
        topStage = 0;

        for (int i = 0; i < listeners.size(); i++)
        {
            listeners.get(i).onDoubleTap(e);
        }
    }
    return true;
}

public boolean onDoubleTapEvent(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onDoubleTapEvent(e);
    }

    return false;
}

public boolean onSingleTapConfirmed(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onSingleTapConfirmed(e);
    }

    return false;
}


public boolean onDown(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onDown(e);
    }

    return false;
}

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onFling(e1, e2, velocityX, velocityY);
    }

    return false;
}

public void onLongPress(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onLongPress(e);
    }
}

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
    if (oneFingerMoveEnable && !onScale)
    {
        xPrevious = xActual;
        yPrevious = yActual;

        xActual = e2.getX() - diferenceFromScaleX;
        yActual = e2.getY() - diferenceFromScaleY;

        if (!firstTimeOnEvent)
        {
            float x = xActual - xPrevious;

            float y = yActual - yPrevious;

            savedMatrix.postTranslate(x, y);

            float[] values = new float[9];

            savedMatrix.getValues(values);

            float leftAux = (float) values[Matrix.MTRANS_X];
            float topAux = (float) values[Matrix.MTRANS_Y];

            float maxTop = 0;
            float maxLeft = 0;

            if (widthStage * currentScaleFactor >= 1280)
            {

                maxLeft = -((float) (widthStage * currentScaleFactor) - (float) 1280);

                if (leftAux < 0)
                {

                    if (leftAux < maxLeft)
                    {

                        maxLeft -= leftAux;
                    }
                    else
                    {

                        maxLeft = 0;
                    }
                }
                else
                {

                    maxLeft = -leftAux;
                }
            }
            else
            {

                maxLeft = ((float) (widthStage * 0.5) - (float) (widthStage * currentScaleFactor * 0.5));

                maxLeft -= leftAux;
            }

            if (heightStage * currentScaleFactor >= 752)
            {

                maxTop = -((float) (heightStage * currentScaleFactor) - (float) 752);

                if (topAux < 0)
                {

                    if (topAux < maxTop)
                    {

                        maxTop -= topAux;
                    }
                    else
                    {

                        maxTop = 0;
                    }
                }
                else
                {

                    maxTop = -topAux;
                }
            }
            else
            {

                maxTop = ((float) (752 * 0.5) - (float) (heightStage * currentScaleFactor * 0.5));


                maxTop -= topAux;
            }

            savedMatrix.postTranslate(maxLeft, maxTop);

            invalidate();
            requestLayout();
        }
        else
        {
            firstTimeOnEvent = false;

            xInitial = e2.getX() - diferenceFromScaleX;
            yInitial = e2.getY() - diferenceFromScaleY;
        }

        float[] values = new float[9];
        savedMatrix.getValues(values);

        leftStage = values[Matrix.MTRANS_X];
        topStage = values[Matrix.MTRANS_Y];
    }

    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onScroll(e1, e2, distanceX, distanceY);
    }

    atualizaParametrosView();

    return true;
}

private void atualizaParametrosView()
{

    RelativeLayout.LayoutParams params = (LayoutParams) this.getChildAt(0).getLayoutParams();

    params.width = widthStage;
    params.height = heightStage;

    this.getChildAt(0).setLayoutParams(params);

    params = (LayoutParams) this.getLayoutParams();

    params.width = widthStage;
    params.height = heightStage;

    this.setLayoutParams(params);

    ((View) this.getParent()).getLayoutParams().width = widthStage;
    ((View) this.getParent()).getLayoutParams().height = heightStage;
}

public void onShowPress(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onShowPress(e);
    }
}

public boolean onSingleTapUp(MotionEvent e)
{
    for (int i = 0; i < listeners.size(); i++)
    {
        listeners.get(i).onSingleTapUp(e);
    }

    return false;
}

// ===================================================================================
// ================================= GETTERS & SETTERS ===============================
// ===================================================================================

public float getScaleFactorActual()
{
    return currentScaleFactor;
}

public float getScaleFactorPrevious()
{
    return previousScaleFactor;
}

public float getxPrevious()
{
    return xPrevious;
}

public float getyPrevious()
{
    return yPrevious;
}

public float getxActual()
{
    return xActual;
}

public float getyActual()
{
    return yActual;
}

public float getLeftStage()
{
    return leftStage;
}

public float getTopStage()
{
    return topStage;
}

public float getxInitial()
{
    return xInitial;
}

public float getyInitial()
{
    return yInitial;
}

public float getMaxScale()
{
    return maxScale;
}

public void setMaxScale(float maxScale)
{
    this.maxScale = maxScale;
}

public float getMinScale()
{
    return minScale;
}

public void setMinScale(float minScale)
{
    this.minScale = minScale;
}

public int getWidthStage()
{
    return widthStage;
}

public void setWidthStage(int widthStage)
{
    this.widthStage = widthStage;
}

public int getHeightStage()
{
    return heightStage;
}

public void setHeightStage(int heightStage)
{
    this.heightStage = heightStage;
}

public boolean isZoomEnable()
{
    return zoomEnable;
}

public void setZoomEnable(boolean zoomEnable)
{
    this.zoomEnable = zoomEnable;
}

public boolean isOneFingerMoveEnable()
{
    return oneFingerMoveEnable;
}

public void setOneFingerMoveEnable(boolean oneFingerMoveEnable)
{
    this.oneFingerMoveEnable = oneFingerMoveEnable;
}

public boolean isTwoFingersMoveEnable()
{
    return twoFingersMoveEnable;
}

public void setTwoFingersMoveEnable(boolean twoFingersMoveEnable)
{
    this.twoFingersMoveEnable = twoFingersMoveEnable;
}

public boolean isDoubleTapZoomEnable()
{
    return doubleTapZoomEnable;
}

public void setDoubleTapZoomEnable(boolean doubleTapZoomEnable)
{
    this.doubleTapZoomEnable = doubleTapZoomEnable;
}