7

レイアウトにImageViewがあり、ImageViewでOnTouchListenerを設定してImageViewをドラッグします。完全に機能しています。私の問題は、ImageViewがレイアウト範囲外に移動するのを防ぐにはどうすればよいですか?

これは私のコードです:

アクティビティクラス:

public class RepositionTestActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.reposition_test_layout);
        ImageView imageView = (ImageView)findViewById(R.id.android);
        imageView.setOnTouchListener(new Touch());
    }
}

タッチクラス:

public class Touch implements OnTouchListener {

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;

    private static final float MIN_ZOOM = 1f;
    private static final float MAX_ZOOM = 5f;

    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();

    private PointF start = new PointF();
    private PointF mid = new PointF();

    private int mode = NONE;
    private float oldDistance = 1f;

    public boolean onTouch(View view, MotionEvent event) {
        ImageView imageView = (ImageView)view;

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

            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX(), event.getY());
                mode = DRAG;
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                oldDistance = spacing(event);
                if(oldDistance > 10f) {
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                    mode = ZOOM;
                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;

            case MotionEvent.ACTION_MOVE:
                if(mode == DRAG) {
                    matrix.set(savedMatrix);
                    matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
                }
                else if(mode == ZOOM) {
                    float newDistance = spacing(event);
                    if(newDistance > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDistance / oldDistance;
                        float[] values = new float[9];
                        matrix.getValues(values);
                        float currentScale = values[Matrix.MSCALE_X];
                        if(scale * currentScale > MAX_ZOOM) 
                            scale = MAX_ZOOM / currentScale;
                        else if (scale * currentScale < MIN_ZOOM)
                            scale = MIN_ZOOM / currentScale;
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
                break;
        }
        imageView.setImageMatrix(matrix);
        return true;
    }

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

    private void midPoint(PointF point, MotionEvent event) {
        point.set((event.getX(0) + event.getX(1)) / 2, (event.getY(0) + event.getY(1)) / 2);
    }

}

レイアウトxml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/reposition_test_layout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ImageView
        android:id="@+id/android"
        android:src="@drawable/android"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:scaleType="matrix"
        android:contentDescription="@string/android_description" >
    </ImageView>

</LinearLayout>

ここに画像の説明を入力してください

4

5 に答える 5

13

Touch次のパラメータをクラスに追加します。

private float dx; // postTranslate X distance
private float dy; // postTranslate Y distance
private float[] matrixValues = new float[9];
float matrixX = 0; // X coordinate of matrix inside the ImageView
float matrixY = 0; // Y coordinate of matrix inside the ImageView
float width = 0; // width of drawable
float height = 0; // height of drawable

後にコードを変更するcase MotionEvent.ACTION_MOVE:

if (mode == DRAG) {
        matrix.set(savedMatrix);

        matrix.getValues(matrixValues);
        matrixX = matrixValues[2];
        matrixY = matrixValues[5];
        width = matrixValues[0] * (((ImageView) view).getDrawable()
                                .getIntrinsicWidth());
        height = matrixValues[4] * (((ImageView) view).getDrawable()
                                .getIntrinsicHeight());

        dx = event.getX() - start.x;
        dy = event.getY() - start.y;

        //if image will go outside left bound
        if (matrixX + dx < 0){
            dx = -matrixX;
        }
        //if image will go outside right bound
        if(matrixX + dx + width > view.getWidth()){
            dx = view.getWidth() - matrixX - width;
        }
        //if image will go oustside top bound
        if (matrixY + dy < 0){
            dy = -matrixY;
        }
        //if image will go outside bottom bound
        if(matrixY + dy + height > view.getHeight()){
            dy = view.getHeight() - matrixY - height;
        }
        matrix.postTranslate(dx, dy);   
    }
于 2012-08-19T20:53:11.510 に答える
1

Androidのドキュメントによると:

getLeft()メソッドとgetTop ()メソッドを呼び出すことにより、ビューの場所を取得することができます。前者は、ビューを表す長方形の左(X)座標を返します。後者は、ビューを表す長方形の上部またはY座標を返します。これらのメソッドは両方とも、親を基準にしたビューの場所を返します 。
さらに、不要な計算を回避するために、いくつかの便利なメソッド、つまりgetRight()getBottom()が提供されています。これらのメソッドは、ビューを表す長方形の右端と下端の座標を返します。たとえば、getRight()の呼び出しは、getLeft()+ getWidth()の計算に似ています。

したがって、画像を移動する前に画像の座標を取得し、 OnTouchListenerクラスで移動の測定値を計算できます。これで、画像が移動しない場合(X coordinate of your image plus horizontal movement that you computed,be greater than device widthまたはY coordinate of your image plus vertical movement that you computed,be greater than device height)。

于 2012-08-19T19:54:49.417 に答える
1

Benito Bertoliからの回答を使用し、ACTION_MOVEコードを変更して、マイナーおよびメジャーの符号を変更し、画像をズームおよびドラッグして画像をズームしました。

これがコードです

private static final float MIN_ZOOM = 1f; 
private static final float MAX_ZOOM = 2.5f; 

public boolean onTouch(View v, MotionEvent event) {
    ImageView view = (ImageView) v;
    view.setScaleType(ImageView.ScaleType.MATRIX);

    // Handle touch events here...
    switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN: //first finger down only
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            Log.d(TAG, "mode=DRAG" );
            mode = DRAG;
            break;
        case MotionEvent.ACTION_UP: //first finger lifted
        case MotionEvent.ACTION_POINTER_UP: //second finger lifted
            mode = NONE;
            Log.d(TAG, "mode=NONE" );
            break;
        case MotionEvent.ACTION_POINTER_DOWN: //second finger down
            oldDist = spacing(event);
            Log.d(TAG, "oldDist=" + oldDist);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
                Log.d(TAG, "mode=ZOOM" );
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                //matrix.set(savedMatrix);
                //matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
                matrix.set(savedMatrix);

                matrix.getValues(matrixValues);
                matrixX = matrixValues[2];
                matrixY = matrixValues[5];
                width = matrixValues[0] * (view.getDrawable().getIntrinsicWidth());
                height = matrixValues[4] * (view.getDrawable().getIntrinsicHeight());


                dx = event.getX() - start.x;
                dy = event.getY() - start.y;

                //if image will go outside left bound
                if (matrixX + dx  > 0){
                    Log.e("dx","lef bound " + dx);
                    dx = -matrixX;
                }
                //if image will go outside right bound
                if(matrixX + dx + width < view.getWidth()){
                    dx = view.getWidth() - matrixX - width;
                }
                //if image will go oustside top bound
                if (matrixY + dy > 0){
                    dy = -matrixY;
                }
                //if image will go outside bottom bound
                if(matrixY + dy + height < view.getHeight()){
                    dy = view.getHeight() - matrixY - height;
                }

                matrix.postTranslate(dx, dy);
            }
            else if (mode == ZOOM) {
                Float newDist = spacing(event);
                Log.d(TAG, "newDist=" + newDist);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = newDist / oldDist;
                    float[] values = new float[9];
                    matrix.getValues(values);
                    float currentScale = values[Matrix.MSCALE_X];
                    if(scale * currentScale > MAX_ZOOM)
                        scale = MAX_ZOOM / currentScale;
                    else if (scale * currentScale < MIN_ZOOM)
                        scale = MIN_ZOOM / currentScale;
                    matrix.postScale(scale, scale, mid.x, mid.y);

                }
                break;
            }
    } //perform the transformation.

    view.setImageMatrix(matrix);
    return true; // indicate event was handled

}

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 void midPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
}

    return drawable;
}
于 2016-02-11T18:35:14.210 に答える
1
  1. ビューの座標に従って、2つのRectオブジェクトを作成する必要があります。1つはビュー用で、もう1つは画像用です。

    float[] values = new float[9];
    matrix.getValues(values);
    float globalX = values[Matrix.MTRANS_X];
    float globalY = values[Matrix.MTRANS_Y];
    float scaleX = values[Matrix.MSCALE_X];
    float scaleY = values[Matrix.MSCALE_Y];
    Rect viewRect = new Rect(0, 0, viewWidth, viewHeight);
    Rect imageRect = new Rect((int) globalX, (int) globalY, Math.round(bitmapWidth * scaleX + globalX),
            Math.round(bitmapHeight * scaleY + globalY));
    
    1. 画像を常にビュー内に配置したい場合は、次のことを確認します。

      if (!viewRect.contains(imageRect)) {
          matrix.set(lastSetMatrix); //return to last saved parameters
      }
      
    2. 画像の一部をビュー内に配置するために、画像を常にビューよりも大きくする必要がある場合があります。これを確認できます。

      if (!imageRect.contains(viewRect)) {
         matrix.set(lastSetMatrix);
      }
      
于 2016-09-08T00:38:53.187 に答える
0

私はこのコードを実行しました。私が雌鶏をズームするとき、それは境界から出てはいけません。正常に動作しますが、x=0とy=0の座標に触れると、最小化されません。

int FLAG=0;   



 else if (mode == ZOOM) {

                    float newDistance = spacing(event);

                    Log.i("new distance ", newDistance+"");

                    matrix.getValues(matrixValues);
                    matrixX = matrixValues[2];
                    matrixY = matrixValues[5];
                    width = matrixValues[0]
                            * (((ImageView) view).getDrawable().getIntrinsicWidth());
                    height = matrixValues[4]
                            * (((ImageView) view).getDrawable()
                                    .getIntrinsicHeight());

                    dx = event.getX() - start.x;
                    dy = event.getY() - start.y;

                    // if image will go outside left bound
                    if (matrixX + dx < 0) {
                        FLAG=1;
                    }
                    if (matrixX + dx + width > view.getWidth()) {
                        FLAG=1;
                        //dx = view.getWidth() - matrixX - width;
                    }
                    // if image will go oustside top bound
                    if (matrixY + dy < 0) {
                        FLAG=1;
                        //dy = -matrixY;
                    }
                    // if image will go outside bottom bound
                    if (matrixY + dy + height > view.getHeight()) {
                        FLAG=1;
                        //dy = view.getHeight() - matrixY - height;
                    }
                if (matrixX + dx ==0 || matrixY + dy==0){ 
                    FLAG=0;
                }

                    if (newDistance > 10f && FLAG==0) {

                        matrix.set(savedMatrix);

                        float scale = newDistance / oldDistance;

                        float[] values = new float[9];

                        matrix.getValues(values);
                        float currentScale = values[Matrix.MSCALE_X];
                        if (scale * currentScale > MAX_ZOOM)
                            scale = MAX_ZOOM / currentScale;
                        else if (scale * currentScale < MIN_ZOOM)
                            scale = MIN_ZOOM / currentScale;
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
                break;
于 2013-10-25T07:16:30.227 に答える