2

我尝试通过展开/捏合手势和相对布局上的拖放功能来实现放大/缩小。

这是我的 OnPinchListener 处理缩放效果的代码。mainView是布局xml文件中定义的RelativeLayout 。

我在fakeview中实现了触摸监听器,它应该在所有视图的前面。触摸事件会根据代码改变主视图。

我想问是否可以在缩放后得到实际的左、上、宽和高?它总是返回 0,0 为左和上,以及缩放后的原始宽度和高度。

非常感谢!

     <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linear_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:id="@+id/zoomable_relative_layout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        >
          <ImageView
            android:id="@+id/imageView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:src="@drawable/background" />
        </RelativeLayout>

    <RelativeLayout
        android:id="@+id/relative_layout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:orientation="vertical" >



    </RelativeLayout>

</RelativeLayout>




public class MainActivity extends Activity {
    //ZoomableRelativeLayout mainView = null;
    RelativeLayout mainView = null;
    RelativeLayout rl = null;
    public static final String TAG = "ZoomText."
            + MainActivity.class.getSimpleName();
    private int offset_x;
    private int offset_y;
    private boolean dragMutex = false;
    RelativeLayout fakeView = null;
    float width = 0, height = 0;
    private OnTouchListener listener = new OnTouchListener() {

        @Override
        public boolean onTouch(View arg0, MotionEvent event) {
            // Log.e(TAG, event + "");
            // Log.e(TAG, "Pointer Count = "+event.getPointerCount());
            Log.e(TAG,
                    event.getX() + "," + event.getY() + "|" + mainView.getX()
                            + "(" + mainView.getWidth() + "),"
                            + mainView.getY() + "(" + mainView.getHeight()
                            + ")");
            if (event.getX() >= mainView.getLeft()
                    && event.getX() <= mainView.getLeft() + mainView.getWidth()
                    && event.getY() >= mainView.getTop()
                    && event.getY() <=mainView.getTop() + mainView.getHeight())
                if (event.getPointerCount() > 1) {
                    return scaleGestureDetector.onTouchEvent(event);
                } else {
                    return llListener.onTouch(arg0, event);
                }
            return false;

        }

    };

    private ScaleGestureDetector scaleGestureDetector;
    private OnTouchListener llListener = new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            // Log.d(TAG, event + ",LL");
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                offset_x = (int) event.getX();
                offset_y = (int) event.getY();
                // Log.e(TAG, offset_x + "," + offset_y);

                dragMutex = true;
                return true;
            case MotionEvent.ACTION_MOVE:
//              Log.e(TAG, "Finger down");
                int x = (int) event.getX() - offset_x;
                int y = (int) event.getY() - offset_y;
                Log.e(TAG, event.getX() + "," + event.getY());
                float _x = mainView.getX();
                float _y = mainView.getY();
                mainView.setX(_x + x);
                mainView.setY(_y + y);
                offset_x = (int) event.getX();
                offset_y = (int) event.getY();
                return true;
            case MotionEvent.ACTION_UP:
                dragMutex = false;
                return true;
            }
            return false;
        }

    };
    private OnDragListener dragListener = new View.OnDragListener() {

        @Override
        public boolean onDrag(View arg0, DragEvent arg1) {
            Log.e(TAG, "DRAG Listener = " + arg1);
            return false;
        }

    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainView = (RelativeLayout) findViewById(R.id.zoomable_relative_layout);
        // mainView.setOnTouchListener(new OnPinchListener());
        // mainView.setOnTouchListener(listener);
        scaleGestureDetector = new ScaleGestureDetector(this,
                new OnPinchListener());
        rl = (RelativeLayout) findViewById(R.id.linear_layout);
        mainView.setOnDragListener(dragListener);
        // mainView.setOnTouchListener(llListener);
        fakeView = (RelativeLayout) findViewById(R.id.relative_layout);
        fakeView.setOnTouchListener(listener);
    }

    class OnPinchListener extends SimpleOnScaleGestureListener {

        float startingSpan;
        float endSpan;
        float startFocusX;
        float startFocusY;

        public boolean onScaleBegin(ScaleGestureDetector detector) {
            startingSpan = detector.getCurrentSpan();
            startFocusX = detector.getFocusX();
            startFocusY = detector.getFocusY();
            return true;
        }

        public boolean onScale(ScaleGestureDetector detector) {
//          mainView.scale(detector.getCurrentSpan() / startingSpan,
//                  startFocusX, startFocusY);
//          if(width==0)
//              width = mainView.getWidth();
//          if(height==0)
//              height = mainView.getHeight();
            mainView.setPivotX(startFocusX);
            mainView.setPivotY(startFocusY);  
            mainView.setScaleX(detector.getCurrentSpan() / startingSpan);
            mainView.setScaleY(detector.getCurrentSpan() / startingSpan);  

//          LayoutParams  para = mainView.getLayoutParams();
//          width*=detector.getCurrentSpan() / startingSpan;
//          height*=detector.getCurrentSpan() / startingSpan;
//          para.width = (int)width;
//          para.height = (int)height;
//          mainView.setLayoutParams(para);


            return true;
        }

        public void onScaleEnd(ScaleGestureDetector detector) {
            //mainView.restore();
            mainView.invalidate();
            Log.e(TAG, mainView.getLeft()+","+mainView.getRight());
        }
    }
}
4

2 回答 2

1

您需要获取转换矩阵并使用它来转换原始点。

所以像这样(在你进行缩放之后):

Matrix m = view.getMatrix(); //gives you the transform matrix
m.mapPoints(newPoints, oldPoints); //transform the original points.
于 2013-06-30T17:46:52.553 回答
0

这就是我在我的情况下解决它的方法(getViewRect应该在布局视图后调用,例如通过view.post(Runnable),因此view.getWidth()/getHeight()返回实际值):

public static Rect getViewRect(View view) {
    Rect outRect = new Rect();
    outRect.right = (int)(view.getWidth() * getScalelX(view));
    outRect.bottom = (int)(view.getHeight() * getScalelY(view));
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    outRect.offset(location[0], location[1]);
    return outRect;
}


public static float getScalelX(View view) {
    float scaleX = view.getScaleX();
    view = getParent(view);
    while (view != null) {
        scaleX *= view.getScaleX();
        view = getParent(view);
    }
    return scaleX;
}

public static float getScalelY(View view) {
    float scaleX = view.getScaleY();
    view = getParent(view);
    while (view != null) {
        scaleX *= view.getScaleY();
        view = getParent(view);
    }
    return scaleX;
}

public static ViewGroup getParent(View view) {
    if (view == null) {
        return null;
    }
    ViewParent parent = view.getParent();
    if (parent instanceof View) {
        return (ViewGroup) parent;
    }
    return null;
}

然而事实证明,android 3.1(也可能是 3.0)在处理方法时没有考虑比例因子getLocationOnScreengetViewRect(View)在像这样的android 3.1 api的情况下,我将在从我的函数返回它之前手动缩放矩形:

public static void scaleRect(Rect rect, float scaleX, float scaleY, float pivotX, float pivotY) {
    rect.left = (int) ((rect.left - pivotX) * scaleX + pivotX);
    rect.right = (int) ((rect.right - pivotX) * scaleX + pivotX);
    rect.top = (int) ((rect.top - pivotY) * scaleY + pivotY);
    rect.bottom = (int) ((rect.bottom - pivotY) * scaleY + pivotY);
}

但是,应该知道层次结构中从当前视图到根的每个视图的枢轴坐标以及相应的缩放级别,以正确处理此转换。

如果有人有任何直接的解决方案,将不胜感激

编辑:

这就是我修改该getViewRect(View)方法的方式,使其也适用于 3.1:

public static Rect getViewRect(View view) {
    Rect outRect = new Rect();
    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2){
        outRect.right = (int)(view.getWidth() * getScalelX(view));
        outRect.bottom = (int)(view.getHeight() * getScalelY(view));
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
    } else {
        outRect.right = view.getWidth();
        outRect.bottom = view.getHeight();
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
        View parent = view;
        while(parent != null){
            parent.getLocationOnScreen(location);
            scaleRect(outRect, parent.getScaleX(), parent.getScaleY(), parent.getPivotX() + location[0], parent.getPivotY() + location[1]);
            parent = getParent(parent);
        }
    }
    return outRect;
}

我认为if可以删除 - 子句,以便第二个分支 ( else) 应该适用于所有版本。但是我更喜欢使用简单的解决方案(第一个分支if),以便第二个只是一种解决方法:)

于 2014-04-17T13:51:48.250 回答