即使我没有触摸Android上的视图,为什么我仍然可以拖动我的自定义视图

时间:2014-09-17 00:19:14

标签: android android-layout

我将自定义视图动态添加到FrameLayout。自定义视图会覆盖onTouchEvent方法,自定义视图也会覆盖onDraw方法以正确地重绘位图。一切正常,但如果我在自定义视图外触摸并开始拖动,它仍会拖动我的自定义视图。这就是我所拥有的:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/custom_view_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:background="@drawable/balloons"
    tools:context="com.blah.test.SomeActivity">
</FrameLayout>

我在SomeActivity.java中添加了我的自定义视图:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.stencil_tigerclaw);
parentView = (FrameLayout) findViewById(R.id.custom_view_container);
stencil = new CustomImageView(this, bitmap, parentView);
parentView.addView(stencil);

这是我的CustomImageView:

public class CustomImageView extends ImageView {
    private Bitmap bitmap;

    private int width;
    private int height;

    private float scale = 1;
    private float angle = 0;

    private Matrix transform = new Matrix();
    private Vector2D position = new Vector2D();
    private TouchManager touchManager = new TouchManager(2);

    private boolean isInitialized = false;

    private FrameLayout parentView;

    public CustomImageView(Context context, Bitmap bitmap, FrameLayout parentView) {
        super(context);

        this.bitmap = bitmap;
        this.width = bitmap.getWidth();
        this.height = bitmap.getHeight();
        this.parentView = parentView;

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        try {
            touchManager.update(event);

            if (touchManager.getPressCount() == 1) {
                position.add(touchManager.moveDelta(0));    
            }
            else {
                if (touchManager.getPressCount() == 2) {
                    Vector2D current = touchManager.getVector(0, 1);
                    Vector2D previous = touchManager.getPreviousVector(0, 1);
                    float currentDistance = current.getLength();
                    float previousDistance = previous.getLength();

                    if (previousDistance != 0) {
                        scale *= currentDistance / previousDistance;
                    }

                    angle -= Vector2D.getSignedAngleBetween(current, previous);
                }
            }

            invalidate();
        }
        catch(Throwable t) {
            // Do something...
        }
        return true;
    }

    public float getAngle() {
        return angle;
    }

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

        if (!isInitialized) {
            position.set(parentView.getWidth()/2, parentView.getHeight()/2);
            isInitialized = true;
        }

        Paint paint = new Paint();

        transform.reset();
        transform.postTranslate(-width / 2.0f, -height / 2.0f);
        transform.postRotate(getDegreesFromRadians(angle));
        transform.postScale(scale, scale);
        transform.postTranslate(position.getX(), position.getY());

        canvas.drawBitmap(bitmap, transform, paint);
    }

最后这是我的TouchManager课程:

public class TouchManager {

    private final int maxNumberOfTouchPoints;

    private final Vector2D[] points;
    private final Vector2D[] previousPoints;

    public TouchManager(final int maxNumberOfTouchPoints) {
        this.maxNumberOfTouchPoints = maxNumberOfTouchPoints;

        points = new Vector2D[maxNumberOfTouchPoints];
        previousPoints = new Vector2D[maxNumberOfTouchPoints];
    }

    public boolean isPressed(int index) {
        return points[index] != null;
    }

    public int getPressCount() {
        int count = 0;
        for(Vector2D point : points) {
            if (point != null)
                ++count;
        }
        return count;
    }

    public Vector2D moveDelta(int index) {

        if (isPressed(index)) {
            Vector2D previous = previousPoints[index] != null ? previousPoints[index] : points[index];
            return Vector2D.subtract(points[index], previous);
        }
        else {
            return new Vector2D();
        }
    }

    private static Vector2D getVector(Vector2D a, Vector2D b) {
        if (a == null || b == null)
            throw new RuntimeException("can't do this on nulls");

        return Vector2D.subtract(b, a);
    }

    public Vector2D getPoint(int index) {
        return points[index] != null ? points[index] : new Vector2D();
    }

    public Vector2D getPreviousPoint(int index) {
        return previousPoints[index] != null ? previousPoints[index] : new Vector2D();
    }

    public Vector2D getVector(int indexA, int indexB) {
        return getVector(points[indexA], points[indexB]);
    }

    public Vector2D getPreviousVector(int indexA, int indexB) {
        if (previousPoints[indexA] == null || previousPoints[indexB] == null)
            return getVector(points[indexA], points[indexB]);
        else
            return getVector(previousPoints[indexA], previousPoints[indexB]);
    }

    public void update(MotionEvent event) {
        int actionCode = event.getAction() & MotionEvent.ACTION_MASK;

        if (actionCode == MotionEvent.ACTION_POINTER_UP || actionCode == MotionEvent.ACTION_UP) {
            int index = event.getAction() >> MotionEvent.ACTION_POINTER_ID_SHIFT;
            previousPoints[index] = points[index] = null;
        }
        else {
            for(int i = 0; i < maxNumberOfTouchPoints; ++i) {
                if (i < event.getPointerCount()) {
                    int index = event.getPointerId(i);

                    Vector2D newPoint = new Vector2D(event.getX(i), event.getY(i));

                    if (points[index] == null)
                        points[index] = newPoint;
                    else {
                        if (previousPoints[index] != null) {
                            previousPoints[index].set(points[index]);
                        }
                        else {
                            previousPoints[index] = new Vector2D(newPoint);

                        }

                        if (Vector2D.subtract(points[index], newPoint).getLength() < 64)
                            points[index].set(newPoint);
                    }
                }
                else {
                    previousPoints[i] = points[i] = null;
                }
            }
        }
    }
}

谢谢!

1 个答案:

答案 0 :(得分:0)

发现我的问题,当您创建自定义视图时,需要覆盖

protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)

正确设置宽度和高度。