user531069
user531069

Reputation: 995

Restricting child view within parent boundries

I am creating a rectangular box and putting an imageView inside it which can be moved. While doing onMove I noticed that imageView is going out of boundries of it's parent view which I don't want. I want to restrict the imageView within the boundaries of it's parent view. How to do that.

Here is the xml:

<FrameLayout
    android:layout_width="400dp"
    android:layout_height="400dp"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:id="@+id/objContainer"
    android:background="@android:color/holo_blue_bright" >
 <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/btn_default" />
</FrameLayout>

</RelativeLayout>

And code to handletouch event:

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            final float x = event.getRawX();
            final float y = event.getRawY();

            // Remember where we started
            mLastTouchX = x;
            mLastTouchY = y;

            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            break;
        case MotionEvent.ACTION_POINTER_UP:
            break;
        case MotionEvent.ACTION_MOVE:


            final float x1 = event.getRawX();
            final float y1 = event.getRawY();

            // Calculate the distance moved
            final float dx = x1 - mLastTouchX;
            final float dy = y1 - mLastTouchY;

            // Move the object
            mPosX += dx;
            mPosY += dy;
            view.setX(mPosX);
            view.setY(mPosY);

            // Remember this touch position for the next move event
            mLastTouchX = x1;
            mLastTouchY = y1;

            // Invalidate to request a redraw
            root.invalidate();
            break;
    }
    return true;
}}

Upvotes: 3

Views: 1681

Answers (1)

Simas
Simas

Reputation: 44158

Inside of your overridden onTouch you need to check if the following move will keep the ImageView inside its container.

In other words you need to check if ImageView's rectangle will stay inside the parent after being moved by dx, dy.

Here's an example:

case MotionEvent.ACTION_MOVE:
    ...
    // Calculate the distance moved
    final float dx = x1 - mLastTouchX;
    final float dy = y1 - mLastTouchY;

    // Make sure we will still be the in parent's container
    Rect parent = new Rect(0, 0, root.getWidth(), root.getHeight());

    int newLeft = (int) (iv.getX() + dx),
            newTop = (int) (iv.getY() + dy),
            newRight = newLeft + iv.getWidth(),
            newBottom = newTop + iv.getHeight();

    if (!parent.contains(newLeft, newTop, newRight, newBottom)) {
        Log.e(TAG, String.format("OOB @ %d, %d - %d, %d",
                newLeft, newTop, newRight, newBottom));
        break;
    }
    ...

Note also that you don't need to invalidate the container, as setX/setY invalidates the ImageView itself.

Upvotes: 7

Related Questions