7

我需要拖动并选择图像集的一部分ImageView并检索所选矩形的端点,而不会导致任何修改(例如裁剪)。

到目前为止,我所能做的就是找出用户点击屏幕的点的坐标。

ImageView imageView = (ImageView) findViewById(R.id.imageView);
imageView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //Simply displays a toast
        Utilities.displayToast(getApplicationContext(), "Touch coordinates : " +
                String.valueOf(event.getX()) + "x" + String.valueOf(event.getY())); 
        return true;
    }
});

但这远不是我想要的。而且我真的无法在 StackOverFlow/Google 上找到任何相关内容。

我该如何实施?

4

3 回答 3

14

这是您可以使用的一种方法(但是,有很多实现相同方法的可能性)。它基于创建用于绘制和跟踪选择矩形的自定义视图。此外,您可以onTouch()在您的自定义视图中应用逻辑OnTouchListener()

主要布局:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:id="@+id/root"
    android:background="@android:color/background_dark">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/image"
        android:src="@drawable/up_image"
        android:scaleType="fitXY" />

    <com.example.TestApp.DragRectView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/dragRect" />

</RelativeLayout>

自定义视图:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class DragRectView extends View {

    private Paint mRectPaint;

    private int mStartX = 0;
    private int mStartY = 0;
    private int mEndX = 0;
    private int mEndY = 0;
    private boolean mDrawRect = false;
    private TextPaint mTextPaint = null;

    private OnUpCallback mCallback = null;

    public interface OnUpCallback {
        void onRectFinished(Rect rect);
    }

    public DragRectView(final Context context) {
        super(context);
        init();
    }

    public DragRectView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragRectView(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    /**
     * Sets callback for up
     *
     * @param callback {@link OnUpCallback}
     */
    public void setOnUpCallback(OnUpCallback callback) {
        mCallback = callback;
    }

    /**
     * Inits internal data
     */
    private void init() {
        mRectPaint = new Paint();
        mRectPaint.setColor(getContext().getResources().getColor(android.R.color.holo_green_light));
        mRectPaint.setStyle(Paint.Style.STROKE);
        mRectPaint.setStrokeWidth(5); // TODO: should take from resources

        mTextPaint = new TextPaint();
        mTextPaint.setColor(getContext().getResources().getColor(android.R.color.holo_green_light));
        mTextPaint.setTextSize(20);
    }

    @Override
    public boolean onTouchEvent(final MotionEvent event) {

        // TODO: be aware of multi-touches
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDrawRect = false;
                mStartX = (int) event.getX();
                mStartY = (int) event.getY();
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:
                final int x = (int) event.getX();
                final int y = (int) event.getY();

                if (!mDrawRect || Math.abs(x - mEndX) > 5 || Math.abs(y - mEndY) > 5) {
                    mEndX = x;
                    mEndY = y;
                    invalidate();
                }

                mDrawRect = true;
                break;

            case MotionEvent.ACTION_UP:
                if (mCallback != null) {
                    mCallback.onRectFinished(new Rect(Math.min(mStartX, mEndX), Math.min(mStartY, mEndY),
                            Math.max(mEndX, mStartX), Math.max(mStartY, mEndY)));
                }
                invalidate();
                break;

            default:
                break;
        }

        return true;
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawRect) {
            canvas.drawRect(Math.min(mStartX, mEndX), Math.min(mStartY, mEndY),
                    Math.max(mEndX, mStartX), Math.max(mEndY, mStartY), mRectPaint);
            canvas.drawText("  (" + Math.abs(mStartX - mEndX) + ", " + Math.abs(mStartY - mEndY) + ")",
                    Math.max(mEndX, mStartX), Math.max(mEndY, mStartY), mTextPaint);
        }
    }
}

活动很简单:

public class MyActivity extends Activity {

    private static final String TAG = "MyActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        final DragRectView view = (DragRectView) findViewById(R.id.dragRect);

        if (null != view) {
            view.setOnUpCallback(new DragRectView.OnUpCallback() {
                @Override
                public void onRectFinished(final Rect rect) {
                    Toast.makeText(getApplicationContext(), "Rect is (" + rect.left + ", " + rect.top + ", " + rect.right + ", " + rect.bottom + ")",
                            Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}

输出如下:

图片

于 2013-09-13T08:32:38.100 回答
1

我刚刚尝试了您的解决方案,这很酷。也许我错了,但我认为您的 Toast 输出中有错字:

mCallback.onRectFinished(new Rect(Math.min(mStartX, mEndX), Math.min(mStartY, mEndY),
                        Math.max(mEndX, mStartX), Math.max(mEndY, mStartX)));

一定是:

mCallback.onRectFinished(new Rect(Math.min(mStartX, mEndX), Math.min(mStartY, mEndY),
                        Math.max(mEndX, mStartX), Math.max(mEndY, mStartY)));

否则有时底部的值计算错误。

于 2014-06-03T17:05:24.323 回答
0

Another way : https://github.com/edmodo/cropper

From the Doc:

The Cropper is an image cropping tool. It provides a way to set an image in XML and programmatically, and displays a resizable crop window on top of the image. Calling the method getCroppedImage() will then return the Bitmap marked by the crop window.

Developers can customize the following attributes (both via XML and programmatically):

appearance of guidelines in the crop window whether the aspect ratio is fixed or not aspect ratio (if the aspect ratio is fixed) image resource A public method to rotate the image by a specified number of degrees is also included. This can be used to provide the user with an option to fix the image orientation should Android miscalculate the intended orientation.

Supported on API Level 7 and above.

For more information, see the linked Github Wiki page.

于 2016-09-03T08:51:19.440 回答