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;
}

getLocationOnScreenただし、Android 3.1(おそらく3.0も)は、メソッドを処理する際にスケールファクターを考慮していないことが判明しました。getViewRect(View)次のような Android 3.1 API の場合、関数から返す前に手動で rect をスケーリングします。

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- 句を削除して、2 番目のブランチ ( else) がすべてのバージョンで機能するようにすることができると思います。ifただし、2番目の解決策が単なる回避策になるように、簡単な解決策(の最初の分岐)を使用することを好みます:)

于 2014-04-17T13:51:48.250 に答える